* Re: [PATCH 2/4] pch_uart: Add Fish River Island II uart clock quirks
From: Alan Cox @ 2012-02-22 8:52 UTC (permalink / raw)
To: Darren Hart
Cc: Linux Kernel Mailing List, Tomoya MORINAGA, Feng Tang,
Greg Kroah-Hartman, Alan Cox, linux-serial
In-Reply-To: <4982ca7a73cfe208a2a5ff0a7e0da54b99ca2d2e.1329875301.git.dvhart@linux.intel.com>
> + /* Setup UART clock, checking for board specific clocks. */
> + uartclk = DEFAULT_UARTCLK;
> +
> + board_name = dmi_get_system_info(DMI_BOARD_NAME);
> + if (board_name && strstr(board_name, "CM-iTC"))
> + uartclk = CMITC_UARTCLK;
> +
> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
> + if (board_name && strstr(board_name, "Fish River Island II"))
> + uartclk = FRI2_UARTCLK;
> +
> + port->uartclk = uartclk;
This is confusing, you load product name into a variable called
board_name ?? perhaps "name" would be clearer ?
>
> if (options)
> uart_parse_options(options, &baud, &parity, &bits, &flow);
> @@ -1566,12 +1580,16 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
> if (!rxbuf)
> goto init_port_free_txbuf;
>
> + /* Setup UART clock, checking for board specific clocks. */
> uartclk = DEFAULT_UARTCLK;
>
> - /* quirk for CM-iTC board */
> board_name = dmi_get_system_info(DMI_BOARD_NAME);
> if (board_name && strstr(board_name, "CM-iTC"))
> - uartclk = 192000000; /* 192.0MHz */
> + uartclk = CMITC_UARTCLK;
> +
> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
> + if (board_name && strstr(board_name, "Fish River Island II"))
> + uartclk = FRI2_UARTCLK;
And we have two locations so this is going to get missed on updates. Can
we have one function for this please ?
Alan
^ permalink raw reply
* Re: [PATCH 0/4] pch_uart: Cleanups, board quirks, and user uartclk parameter
From: Alan Cox @ 2012-02-22 8:58 UTC (permalink / raw)
To: Tomoya MORINAGA
Cc: Darren Hart, Linux Kernel Mailing List, Feng Tang,
Greg Kroah-Hartman, Alan Cox, linux-serial
In-Reply-To: <CANKRQni9E6NO39MFSak6MjQ0DtmQeviGo966Ex9ZUvai56wCjg@mail.gmail.com>
> > assume a 192 MHz clock on all boards. The problem with this approach is
> > that the CLKCFG register may have been set to something other than the
> > 192MHz configuration by the firmware.
So you can use the early PCI hooks or even bash the register directly in
your early bootup code. You won't be the only early boot console that
does this sort of thing. There are even people bitbanging PCI I²C
interfaces at boot time for such purpose.
> So, I think default uart_clock 192MHz setting is better than Darren's opinion.
It's certainly easier to maintain, but it would be good to know if the
setting can be written or retrieved directly in the early console setup
using the early PCI ops or similar.
Alan
Alan
^ permalink raw reply
* Re: [PATCH 0/4] pch_uart: Cleanups, board quirks, and user uartclk parameter
From: Darren Hart @ 2012-02-22 8:59 UTC (permalink / raw)
To: Tomoya MORINAGA
Cc: Linux Kernel Mailing List, Feng Tang, Greg Kroah-Hartman,
Alan Cox, linux-serial
In-Reply-To: <CANKRQngnFhTY3-YxhDH3oufbqUu5pe36Fi58DjKWm=9uTigr-A@mail.gmail.com>
On 02/22/2012 12:16 AM, Tomoya MORINAGA wrote:
> 2012年2月22日15:39 Darren Hart <dvhart@linux.intel.com>:
>> We can add a patch to this series that sets the
>> default to 192MHz, drops the CM-iTC quirk, and does nothing in pch_phub
>> probe for the FRI2.
>
> If you set the clock of pch_uart as 64MHz,
> do you need to add quirk for FRI2 to pch_phub so as to provide 64MHz clock?
I admit the value of pch_phub eludes me a bit. In my case, the firmware
sets up the CLKCFG register, so there is no need to set it manually
after boot. Instead, I'm making sure the pch_uart driver defaults to
what the firmware sets up.
--
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel
^ permalink raw reply
* Re: [PATCH] serial/sirf: fixup for changes to pin control
From: Barry Song @ 2012-02-22 9:14 UTC (permalink / raw)
To: Linus Walleij
Cc: linux-kernel, linux-arm-kernel, Stephen Warren, Shawn Guo,
Thomas Abraham, Dong Aisheng, Rajendra Nayak, Haojian Zhuang,
Tony Lindgren, linux-serial, DL-SHA-WorkGroupLinux
In-Reply-To: <1329417828-6005-1-git-send-email-linus.walleij@linaro.org>
2012/2/17 Linus Walleij <linus.walleij@linaro.org>:
> We changed the signature of the pin multiplexing functions to
> handle any pin business, so fix up the Sirf driver to call this
> new interface and rename some variables to make the semantics
> understandable.
>
> Cc: linux-serial@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Barry Song <Baohua.Song@csr.com>
> ---
> drivers/tty/serial/sirfsoc_uart.c | 20 ++++++++++----------
> drivers/tty/serial/sirfsoc_uart.h | 2 +-
> 2 files changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
> index a60523f..c1a871e 100644
> --- a/drivers/tty/serial/sirfsoc_uart.c
> +++ b/drivers/tty/serial/sirfsoc_uart.c
> @@ -22,7 +22,7 @@
> #include <linux/io.h>
> #include <asm/irq.h>
> #include <asm/mach/irq.h>
> -#include <linux/pinctrl/pinmux.h>
> +#include <linux/pinctrl/consumer.h>
>
> #include "sirfsoc_uart.h"
>
> @@ -673,12 +673,12 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
> port->irq = res->start;
>
> if (sirfport->hw_flow_ctrl) {
> - sirfport->pmx = pinmux_get(&pdev->dev, NULL);
> - ret = IS_ERR(sirfport->pmx);
> + sirfport->p = pinctrl_get(&pdev->dev, NULL);
> + ret = IS_ERR(sirfport->p);
> if (ret)
> - goto pmx_err;
> + goto pin_err;
>
> - pinmux_enable(sirfport->pmx);
> + pinctrl_enable(sirfport->p);
> }
>
> port->ops = &sirfsoc_uart_ops;
> @@ -696,10 +696,10 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
> port_err:
> platform_set_drvdata(pdev, NULL);
> if (sirfport->hw_flow_ctrl) {
> - pinmux_disable(sirfport->pmx);
> - pinmux_put(sirfport->pmx);
> + pinctrl_disable(sirfport->p);
> + pinctrl_put(sirfport->p);
> }
> -pmx_err:
> +pin_err:
> irq_err:
> devm_iounmap(&pdev->dev, port->membase);
> err:
> @@ -712,8 +712,8 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
> struct uart_port *port = &sirfport->port;
> platform_set_drvdata(pdev, NULL);
> if (sirfport->hw_flow_ctrl) {
> - pinmux_disable(sirfport->pmx);
> - pinmux_put(sirfport->pmx);
> + pinctrl_disable(sirfport->p);
> + pinctrl_put(sirfport->p);
> }
> devm_iounmap(&pdev->dev, port->membase);
> uart_remove_one_port(&sirfsoc_uart_drv, port);
> diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h
> index fc64260..6e207fd 100644
> --- a/drivers/tty/serial/sirfsoc_uart.h
> +++ b/drivers/tty/serial/sirfsoc_uart.h
> @@ -162,7 +162,7 @@ struct sirfsoc_uart_port {
> unsigned char ms_enabled;
>
> struct uart_port port;
> - struct pinmux *pmx;
> + struct pinctrl *p;
> };
>
> /* Hardware Flow Control */
> --
> 1.7.7.6
>
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/4] pch_uart: Cleanups, board quirks, and user uartclk parameter
From: Feng Tang @ 2012-02-22 9:25 UTC (permalink / raw)
To: Darren Hart
Cc: Tomoya MORINAGA, Linux Kernel Mailing List, Greg Kroah-Hartman,
Alan Cox, linux-serial
In-Reply-To: <4F44AE57.10302@linux.intel.com>
On Wed, Feb 22, 2012 at 12:59:03AM -0800, Darren Hart wrote:
>
>
> On 02/22/2012 12:16 AM, Tomoya MORINAGA wrote:
> > 2012年2月22日15:39 Darren Hart <dvhart@linux.intel.com>:
> >> We can add a patch to this series that sets the
> >> default to 192MHz, drops the CM-iTC quirk, and does nothing in pch_phub
> >> probe for the FRI2.
> >
> > If you set the clock of pch_uart as 64MHz,
> > do you need to add quirk for FRI2 to pch_phub so as to provide 64MHz clock?
>
> I admit the value of pch_phub eludes me a bit. In my case, the firmware
> sets up the CLKCFG register, so there is no need to set it manually
> after boot. Instead, I'm making sure the pch_uart driver defaults to
> what the firmware sets up.
I think long term wise, we should suggest BIOS vendor to set the UART clk
to 192MHz in chipset's release notes, since 192MHz works on Darren's,
Tomoya's and my boards.
Thanks,
Feng
>
> --
> Darren Hart
> Intel Open Source Technology Center
> Yocto Project - Linux Kernel
^ permalink raw reply
* Re: About changing Line Discipline from Kernel
From: Alan Cox @ 2012-02-22 9:34 UTC (permalink / raw)
To: Mayank Rana; +Cc: linux-serial
In-Reply-To: <4F4493AC.5010405@codeaurora.org>
> 1. I understand that line discipline can be changed from user space
> application by opening the device and doing ioctl with required Line
> Discipline ID. Is it possible to do the same from kernel module who
> would be communicating with that line discipline ?
Not currently. You need something to hold the tty open anyway if you do
this.
> 2. Is it way to set default line discipline for particular tty device
> to required Line Discipline instead of N_TTY one ?
No. All tty devices start in N_TTY and return to N_TTY when closed.
That's a design assumption in the ldisc handling and in in the tty setup
and teardown code paths.
There is no API/ABI reason for the assumption so if someone did the work
they could remove that assumption.
Alan
^ permalink raw reply
* Re: [PATCH 2/4] pch_uart: Add Fish River Island II uart clock quirks
From: Darren Hart @ 2012-02-22 9:46 UTC (permalink / raw)
To: Alan Cox
Cc: Linux Kernel Mailing List, Tomoya MORINAGA, Feng Tang,
Greg Kroah-Hartman, Alan Cox, linux-serial
In-Reply-To: <20120222085250.193096c9@pyramind.ukuu.org.uk>
On 02/22/2012 12:52 AM, Alan Cox wrote:
>> + /* Setup UART clock, checking for board specific clocks. */
>> + uartclk = DEFAULT_UARTCLK;
>> +
>> + board_name = dmi_get_system_info(DMI_BOARD_NAME);
>> + if (board_name && strstr(board_name, "CM-iTC"))
>> + uartclk = CMITC_UARTCLK;
>> +
>> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
>> + if (board_name && strstr(board_name, "Fish River Island II"))
>> + uartclk = FRI2_UARTCLK;
>> +
>> + port->uartclk = uartclk;
>
> This is confusing, you load product name into a variable called
> board_name ?? perhaps "name" would be clearer ?
OK, done.
>
>>
>> if (options)
>> uart_parse_options(options, &baud, &parity, &bits, &flow);
>> @@ -1566,12 +1580,16 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
>> if (!rxbuf)
>> goto init_port_free_txbuf;
>>
>> + /* Setup UART clock, checking for board specific clocks. */
>> uartclk = DEFAULT_UARTCLK;
>>
>> - /* quirk for CM-iTC board */
>> board_name = dmi_get_system_info(DMI_BOARD_NAME);
>> if (board_name && strstr(board_name, "CM-iTC"))
>> - uartclk = 192000000; /* 192.0MHz */
>> + uartclk = CMITC_UARTCLK;
>> +
>> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
>> + if (board_name && strstr(board_name, "Fish River Island II"))
>> + uartclk = FRI2_UARTCLK;
>
> And we have two locations so this is going to get missed on updates. Can
> we have one function for this please ?
Right, bad dvhart. Done. That cleans things up nicely. I'll resend as V2
after considering your 0/4 response....
--
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel
^ permalink raw reply
* Re: [PATCH 0/4] pch_uart: Cleanups, board quirks, and user uartclk parameter
From: Darren Hart @ 2012-02-22 9:55 UTC (permalink / raw)
To: Alan Cox
Cc: Tomoya MORINAGA, Linux Kernel Mailing List, Feng Tang,
Greg Kroah-Hartman, Alan Cox, linux-serial
In-Reply-To: <20120222085830.1ed8c25e@pyramind.ukuu.org.uk>
On 02/22/2012 12:58 AM, Alan Cox wrote:
>>> assume a 192 MHz clock on all boards. The problem with this approach is
>>> that the CLKCFG register may have been set to something other than the
>>> 192MHz configuration by the firmware.
>
> So you can use the early PCI hooks or even bash the register directly in
> your early bootup code. You won't be the only early boot console that
> does this sort of thing. There are even people bitbanging PCI I²C
> interfaces at boot time for such purpose.
>
>> So, I think default uart_clock 192MHz setting is better than Darren's opinion.
>
> It's certainly easier to maintain, but it would be good to know if the
> setting can be written or retrieved directly in the early console setup
> using the early PCI ops or similar.
OK, I'm not opposed to forcing everything to 192MHz, that would clean up
pch_uart.c quite a bit. I have heard different things about the
specification for this chipset. One statement was that 64MHz was the
maximum UART clock. Feng suggests that 192MHz is the recommended UART
clock. I need to dig up this spec and determine what it actually says.
I have V2 with Alan's feedback from 2/4 incorporated, but I'll hold off
unless people want to see it now. Seems like it will change a lot if we
force 192MHz everywhere.
--
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] serial: samsung: fix s3c2442 platform data
From: Denis 'GNUtoo' Carikli @ 2012-02-23 7:23 UTC (permalink / raw)
To: linux-serial; +Cc: Denis 'GNUtoo' Carikli
Without that fix machines having a s3c2442 CPU have something
like that in dmesg:
samsung-uart s3c2440-uart.0: could not find driver data
samsung-uart s3c2440-uart.1: could not find driver data
samsung-uart s3c2440-uart.2: could not find driver data
And serial is never initialized.
The previous log was obtained trough early printk on the gta02
machine.
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
---
drivers/tty/serial/samsung.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index c55e5fb..de249d2 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1507,7 +1507,7 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
#endif
#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
- defined(CONFIG_CPU_S3C2443)
+ defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2440 UART",
--
1.7.4.1
^ permalink raw reply related
* [PATCH V2 09/14] SERIAL: MIPS: lantiq: convert serial driver to clkdev api
From: John Crispin @ 2012-02-23 16:03 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, John Crispin, linux-serial
In-Reply-To: <1330012993-13510-1-git-send-email-blogic@openwrt.org>
Reference the FPI clock via its new access function.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-serial@vger.kernel.org
---
drivers/tty/serial/lantiq.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 96c1cac..99fb70f 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -686,7 +686,7 @@ lqasc_probe(struct platform_device *pdev)
if (lqasc_port[pdev->id] != NULL)
return -EBUSY;
- clk = clk_get(&pdev->dev, "fpi");
+ clk = clk_get_fpi();
if (IS_ERR(clk)) {
pr_err("failed to get fpi clk\n");
return -ENOENT;
--
1.7.7.1
^ permalink raw reply related
* Re: [PATCH 2/3] tty: serial: OMAP: block idle while the UART is transferring data in PIO mode
From: Cousson, Benoit @ 2012-02-24 14:35 UTC (permalink / raw)
To: Paul Walmsley
Cc: linux-omap, linux-serial, linux-arm-kernel, Kevin Hilman,
Govindraj.R, Greg Kroah-Hartman, Alan Cox, Tomi Valkeinen,
Nayak, Rajendra
In-Reply-To: <alpine.DEB.2.00.1202211456160.25023@utopia.booyaka.com>
Salut Paul,
On 2/21/2012 11:02 PM, Paul Walmsley wrote:
> Salut Benoît,
>
> On Mon, 20 Feb 2012, Cousson, Benoit wrote:
>
>> 3.3-rc4 is broken in the DT case because of the serial driver. And it
>> looks like it is due to this fix. We cannot rely on pdata anymore in
>> DT, and in that case it leads to an Oops due to NULL pdata.
>
> Sorry about the breakage. I agree with the diagnosis. That code was just
> copied from the DMA errata part of the driver, so it will need to be fixed
> as well. Otherwise the same problem will happen when DMA is enabled.
>
>> And then we will have to add the support for all these OMAP custom hooks without pdata.
>
> That's really the key question for the medium- to long-term...
I know you know, I'm always hoping that someone will step up and propose
some cool idea to fix that :-)
>> A basic fix (below) for the moment is to test for valid pdata inside the driver.
>> I'll repost it properly if you are fine with it.
>
> Looks fine to me, although I'd suggest fixing the DMA workaround path as
> well.
Mmm, I've tried to fix every instances of pdata in the code, you think I
missed some?
I'll check again.
> Reviewed-by: Paul Walmsley<paul@pwsan.com>
Thanks,
Benoit
--
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] serial/amba-pl011: Return early in deadlock work-around if there is no tty
From: Greg KH @ 2012-02-24 21:47 UTC (permalink / raw)
To: Kalle Vahlman; +Cc: linux-serial, stable
In-Reply-To: <1329718024-23623-1-git-send-email-kalle.vahlman@movial.com>
On Mon, Feb 20, 2012 at 08:07:04AM +0200, Kalle Vahlman wrote:
> The first amba port does not always have an attached tty, which will
> result in a crash if the work-around is activated.
>
> This seems to be the case for example on Snowball which has no modem
> hw, which seems to be the main use-case for this work-around.
> ---
> drivers/tty/serial/amba-pl011.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
Can you re-read Documentation/SubmittingPatches and resend this patch
with the needed information so that I can apply it (hint, you forgot a
signed-off-by: line...)
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 2/4] pch_uart: Add Fish River Island II uart clock quirks
From: Greg Kroah-Hartman @ 2012-02-24 21:53 UTC (permalink / raw)
To: Darren Hart
Cc: Alan Cox, Linux Kernel Mailing List, Tomoya MORINAGA, Feng Tang,
Alan Cox, linux-serial
In-Reply-To: <4F44B95E.3030307@linux.intel.com>
On Wed, Feb 22, 2012 at 01:46:06AM -0800, Darren Hart wrote:
>
>
> On 02/22/2012 12:52 AM, Alan Cox wrote:
> >> + /* Setup UART clock, checking for board specific clocks. */
> >> + uartclk = DEFAULT_UARTCLK;
> >> +
> >> + board_name = dmi_get_system_info(DMI_BOARD_NAME);
> >> + if (board_name && strstr(board_name, "CM-iTC"))
> >> + uartclk = CMITC_UARTCLK;
> >> +
> >> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
> >> + if (board_name && strstr(board_name, "Fish River Island II"))
> >> + uartclk = FRI2_UARTCLK;
> >> +
> >> + port->uartclk = uartclk;
> >
> > This is confusing, you load product name into a variable called
> > board_name ?? perhaps "name" would be clearer ?
>
> OK, done.
"Done" where? Is there a newer patch series I should be looking at
here to apply? I'm guessing I can ignore this one, right?
consider it ignored :)
greg k-h
^ permalink raw reply
* Re: [PATCH 2/4] pch_uart: Add Fish River Island II uart clock quirks
From: Darren Hart @ 2012-02-24 22:25 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alan Cox, Linux Kernel Mailing List, Tomoya MORINAGA, Feng Tang,
Alan Cox, linux-serial
In-Reply-To: <20120224215315.GC25330@kroah.com>
On 02/24/2012 01:53 PM, Greg Kroah-Hartman wrote:
> On Wed, Feb 22, 2012 at 01:46:06AM -0800, Darren Hart wrote:
>>
>>
>> On 02/22/2012 12:52 AM, Alan Cox wrote:
>>>> + /* Setup UART clock, checking for board specific clocks. */
>>>> + uartclk = DEFAULT_UARTCLK;
>>>> +
>>>> + board_name = dmi_get_system_info(DMI_BOARD_NAME);
>>>> + if (board_name && strstr(board_name, "CM-iTC"))
>>>> + uartclk = CMITC_UARTCLK;
>>>> +
>>>> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
>>>> + if (board_name && strstr(board_name, "Fish River Island II"))
>>>> + uartclk = FRI2_UARTCLK;
>>>> +
>>>> + port->uartclk = uartclk;
>>>
>>> This is confusing, you load product name into a variable called
>>> board_name ?? perhaps "name" would be clearer ?
>>
>> OK, done.
>
> "Done" where? Is there a newer patch series I should be looking at
> here to apply? I'm guessing I can ignore this one, right?
>
> consider it ignored :)
I have the V2 patch series here, tested it, was going to send it today
.... then received a new revision of the hardware/firmware which hides
the PCI device and the UART is driven by the 8250 driver and requires me
to use 3318 as the baud ..... ***sigh***. I'm not sure what the right
thing is to do right now. I'm going to have a conversation with the
hardware manufacturer and the TWO firmware teams I'm working with.
If anyone has experience with this sort of mess and would like to offer
a recommended course of action, I'm all ears.
--
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel
^ permalink raw reply
* Re: [PATCH 2/4] pch_uart: Add Fish River Island II uart clock quirks
From: Greg Kroah-Hartman @ 2012-02-24 23:39 UTC (permalink / raw)
To: Darren Hart
Cc: Alan Cox, Linux Kernel Mailing List, Tomoya MORINAGA, Feng Tang,
Alan Cox, linux-serial
In-Reply-To: <4F480E6B.90301@linux.intel.com>
On Fri, Feb 24, 2012 at 02:25:47PM -0800, Darren Hart wrote:
>
>
> On 02/24/2012 01:53 PM, Greg Kroah-Hartman wrote:
> > On Wed, Feb 22, 2012 at 01:46:06AM -0800, Darren Hart wrote:
> >>
> >>
> >> On 02/22/2012 12:52 AM, Alan Cox wrote:
> >>>> + /* Setup UART clock, checking for board specific clocks. */
> >>>> + uartclk = DEFAULT_UARTCLK;
> >>>> +
> >>>> + board_name = dmi_get_system_info(DMI_BOARD_NAME);
> >>>> + if (board_name && strstr(board_name, "CM-iTC"))
> >>>> + uartclk = CMITC_UARTCLK;
> >>>> +
> >>>> + board_name = dmi_get_system_info(DMI_PRODUCT_NAME);
> >>>> + if (board_name && strstr(board_name, "Fish River Island II"))
> >>>> + uartclk = FRI2_UARTCLK;
> >>>> +
> >>>> + port->uartclk = uartclk;
> >>>
> >>> This is confusing, you load product name into a variable called
> >>> board_name ?? perhaps "name" would be clearer ?
> >>
> >> OK, done.
> >
> > "Done" where? Is there a newer patch series I should be looking at
> > here to apply? I'm guessing I can ignore this one, right?
> >
> > consider it ignored :)
>
> I have the V2 patch series here, tested it, was going to send it today
> .... then received a new revision of the hardware/firmware which hides
> the PCI device and the UART is driven by the 8250 driver and requires me
> to use 3318 as the baud ..... ***sigh***. I'm not sure what the right
> thing is to do right now. I'm going to have a conversation with the
> hardware manufacturer and the TWO firmware teams I'm working with.
>
> If anyone has experience with this sort of mess and would like to offer
> a recommended course of action, I'm all ears.
A big stick is usually best to use on the firmware engineers...
Good luck,
greg k-h
^ permalink raw reply
* USB Smart Card reader
From: James Courtier-Dutton @ 2012-02-25 10:01 UTC (permalink / raw)
To: linux-serial
Hi,
I have done some development work on the iuu_phoenix.c driver in the
Linux kernel.
The iuu_phoenix is a smart card reader.
The smart card reader can be given a unique identification string of
16 characters/hex bytes. This ID can be read when the card reader is
inserted into the USB port.
I would like to be able to set up device names in /dev so that when
inserting a card reader into the USB port, it always will appear with
the same unique name in /dev.
Similar to the by-uuid used for hard disk drives.
Can someone tell me how to do this, or probably better, point me to an
existing driver that does it within the linux/drivers/usb/serial tree.
Kind Regards
James
^ permalink raw reply
* Re: [PATCH] serial/amba-pl011: Return early in deadlock work-around if there is no tty
From: Kalle Vahlman @ 2012-02-25 10:57 UTC (permalink / raw)
To: Greg KH; +Cc: linux-serial, stable
In-Reply-To: <20120224214743.GA25330@kroah.com>
2012/2/24 Greg KH <gregkh@linuxfoundation.org>:
> On Mon, Feb 20, 2012 at 08:07:04AM +0200, Kalle Vahlman wrote:
>> The first amba port does not always have an attached tty, which will
>> result in a crash if the work-around is activated.
>>
>> This seems to be the case for example on Snowball which has no modem
>> hw, which seems to be the main use-case for this work-around.
>> ---
>> drivers/tty/serial/amba-pl011.c | 4 ++++
>> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> Can you re-read Documentation/SubmittingPatches and resend this patch
> with the needed information so that I can apply it (hint, you forgot a
> signed-off-by: line...)
Ah, sorry for that. But actually I was alerted to a plan to eradicate
the whole workaround so this patch can be left unapplied.
I will follow up with a new submission if that doesn't happen soon.
Cheers,
--
Kalle Vahlman, Movial Creative Technologies Inc.
Porkkalankatu 20, FI-00180 Helsinki
Tel +358 9 8567 6400
Fax +358 9 8567 6401
www.movial.com
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* (unknown),
From: Grieger, Anne @ 2012-02-25 14:29 UTC (permalink / raw)
Do you need a loan?? Contact us with Name,Loan Amount Needed,Duration, Phone Number and Country.
Reply Below
Name: Mr Harry Fernandez
Email: harry.fernandez01@hotmail.com<mailto:harry.fernandez01@hotmail.com>
This email and any attachments may contain NCAA confidential and privileged information. If you are not the intended recipient, please notify the sender immediately by return email, delete this message and destroy any copies. Any dissemination or use of this information by a person other than the intended recipient is unauthorized and may be illegal.
^ permalink raw reply
* Re: USB Smart Card reader
From: Greg KH @ 2012-02-25 16:41 UTC (permalink / raw)
To: James Courtier-Dutton; +Cc: linux-serial
In-Reply-To: <CAAMvbhFzJv4EpQt4LavFeFusJsCDrFQ1EGhCdvgPG9q63s2AyA@mail.gmail.com>
On Sat, Feb 25, 2012 at 10:01:17AM +0000, James Courtier-Dutton wrote:
> Hi,
>
> I have done some development work on the iuu_phoenix.c driver in the
> Linux kernel.
> The iuu_phoenix is a smart card reader.
> The smart card reader can be given a unique identification string of
> 16 characters/hex bytes. This ID can be read when the card reader is
> inserted into the USB port.
> I would like to be able to set up device names in /dev so that when
> inserting a card reader into the USB port, it always will appear with
> the same unique name in /dev.
> Similar to the by-uuid used for hard disk drives.
Your distro should already have /dev/serial/ which provides this for you
automatically. Have you used that and found it somehow lacking?
greg k-h
^ permalink raw reply
* [PATCH] Clear previous interrupts after fifo is disabled
From: Chanho Min @ 2012-02-27 9:30 UTC (permalink / raw)
To: Russell King, Alan Cox, Greg Kroah-Hartman, Linus Walleij,
Shreshtha Kumar Sahu, Kim, Jong-Sung
Cc: linux-kernel, linux-serial
This is another workaroud of 'https://lkml.org/lkml/2012/1/17/104'
with additional analysis.Bootloader can transfer control to kernel and
there are some pending interrupts. In this case, RXFE of the flag
register is set by clearing FEN(LCRH) even if rx data remains in the
fifo. It seems that the fifo's status is initiailized. Interrupt
handler can not get any data from data register because of the below
break condtion.
pl011_fifo_to_tty
while (max_count--) {
if (status & UART01x_FR_RXFE)
break;
Then, Rx interrupt is never cleared. cpu is looping in ISR. System is
hang. If we don't guarantee that no interrupt is pended until fifo is
disabled by calling 'writew(0, uap->port.membase + uap->lcrh_rx)',
this misbehave of the interrupt handelr can be occurred. So, All
pending interrupts should be cleared just after fifo is disabled under
the protection from interrupt. Also,'clear error interrupts' routine
can be removed becuase all interrupts are cleared before.
Signed-off-by: Chanho Min <chanho.min@lge.com>
---
drivers/tty/serial/amba-pl011.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6800f5f..8b5a824 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1397,7 +1397,11 @@ static int pl011_startup(struct uart_port *port)
writew(cr, uap->port.membase + UART011_CR);
writew(0, uap->port.membase + UART011_FBRD);
writew(1, uap->port.membase + UART011_IBRD);
+ spin_lock_irq(&uap->port.lock);
writew(0, uap->port.membase + uap->lcrh_rx);
+ /* Clear all pending interrupts. */
+ writew(0xffff, uap->port.membase + UART011_ICR);
+ spin_unlock_irq(&uap->port.lock);
if (uap->lcrh_tx != uap->lcrh_rx) {
int i;
/*
@@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_port *port)
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
- /* Clear pending error interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
-
/*
* initialise the old status of the modem signals
*/
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] Clear previous interrupts after fifo is disabled
From: Linus Walleij @ 2012-02-27 10:45 UTC (permalink / raw)
To: Chanho Min
Cc: Russell King, Alan Cox, Greg Kroah-Hartman, Shreshtha Kumar Sahu,
Kim, Jong-Sung, linux-kernel, linux-serial
In-Reply-To: <CAOAMb1ASB0zznSSOAU9HgPNW2e=Do+8hSJ6JZ00DxtAxqsXyXQ@mail.gmail.com>
On Mon, Feb 27, 2012 at 10:30 AM, Chanho Min <chanho0207@gmail.com> wrote:
> This is another workaroud of 'https://lkml.org/lkml/2012/1/17/104'
> with additional analysis.Bootloader can transfer control to kernel and
> there are some pending interrupts. In this case, RXFE of the flag
> register is set by clearing FEN(LCRH) even if rx data remains in the
> fifo. It seems that the fifo's status is initiailized. Interrupt
> handler can not get any data from data register because of the below
> break condtion.
>
> pl011_fifo_to_tty
> while (max_count--) {
> if (status & UART01x_FR_RXFE)
> break;
>
> Then, Rx interrupt is never cleared. cpu is looping in ISR. System is
> hang. If we don't guarantee that no interrupt is pended until fifo is
> disabled by calling 'writew(0, uap->port.membase + uap->lcrh_rx)',
> this misbehave of the interrupt handelr can be occurred. So, All
> pending interrupts should be cleared just after fifo is disabled under
> the protection from interrupt. Also,'clear error interrupts' routine
> can be removed becuase all interrupts are cleared before.
>
> Signed-off-by: Chanho Min <chanho.min@lge.com>
Looks correct to me.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Thanks,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] Clear previous interrupts after fifo is disabled
From: Russell King - ARM Linux @ 2012-02-27 10:48 UTC (permalink / raw)
To: Chanho Min
Cc: Alan Cox, Greg Kroah-Hartman, Linus Walleij, Shreshtha Kumar Sahu,
Kim, Jong-Sung, linux-kernel, linux-serial
In-Reply-To: <CAOAMb1ASB0zznSSOAU9HgPNW2e=Do+8hSJ6JZ00DxtAxqsXyXQ@mail.gmail.com>
On Mon, Feb 27, 2012 at 06:30:20PM +0900, Chanho Min wrote:
> This is another workaroud of 'https://lkml.org/lkml/2012/1/17/104'
> with additional analysis.Bootloader can transfer control to kernel and
> there are some pending interrupts. In this case, RXFE of the flag
> register is set by clearing FEN(LCRH) even if rx data remains in the
> fifo. It seems that the fifo's status is initiailized. Interrupt
> handler can not get any data from data register because of the below
> break condtion.
>
> pl011_fifo_to_tty
> while (max_count--) {
> if (status & UART01x_FR_RXFE)
> break;
>
> Then, Rx interrupt is never cleared. cpu is looping in ISR. System is
> hang. If we don't guarantee that no interrupt is pended until fifo is
> disabled by calling 'writew(0, uap->port.membase + uap->lcrh_rx)',
> this misbehave of the interrupt handelr can be occurred. So, All
> pending interrupts should be cleared just after fifo is disabled under
> the protection from interrupt. Also,'clear error interrupts' routine
> can be removed becuase all interrupts are cleared before.
I'd much prefer to only clear those interrupts which actually need to be
cleared at this point. So, I'd suggest this approach instead:
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6800f5f..a13a825 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1381,6 +1381,10 @@ static int pl011_startup(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk);
+ /* Clear pending error and receive interrupts */
+ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
+ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+
/*
* Allocate the IRQ
*/
@@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_port *port)
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
- /* Clear pending error interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
-
/*
* initialise the old status of the modem signals
*/
^ permalink raw reply related
* Re: [PATCH] Clear previous interrupts after fifo is disabled
From: Russell King - ARM Linux @ 2012-02-27 11:02 UTC (permalink / raw)
To: Chanho Min
Cc: Alan Cox, Greg Kroah-Hartman, Linus Walleij, Shreshtha Kumar Sahu,
Kim, Jong-Sung, linux-kernel, linux-serial
In-Reply-To: <20120227104858.GR22562@n2100.arm.linux.org.uk>
On Mon, Feb 27, 2012 at 10:48:58AM +0000, Russell King - ARM Linux wrote:
> I'd much prefer to only clear those interrupts which actually need to be
> cleared at this point. So, I'd suggest this approach instead:
Thinking about this a little more, we definitely want to mask and clear
interrupts at probe time as well:
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6800f5f..6b781bd 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1381,6 +1381,10 @@ static int pl011_startup(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk);
+ /* Clear pending error and receive interrupts */
+ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
+ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+
/*
* Allocate the IRQ
*/
@@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_port *port)
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
- /* Clear pending error interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
-
/*
* initialise the old status of the modem signals
*/
@@ -1927,6 +1927,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
goto unmap;
}
+ /* Ensure interrupts from this UART are masked and cleared */
+ writew(0, uap->port.membase + UART011_IMSC);
+ writew(0xffff, uap->port.membase + UART011_ICR);
+
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
^ permalink raw reply related
* Re: [PATCH] Clear previous interrupts after fifo is disabled
From: Linus Walleij @ 2012-02-27 13:54 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Chanho Min, Alan Cox, Greg Kroah-Hartman, Shreshtha Kumar Sahu,
Kim, Jong-Sung, linux-kernel, linux-serial
In-Reply-To: <20120227110204.GA30199@n2100.arm.linux.org.uk>
On Mon, Feb 27, 2012 at 12:02 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Feb 27, 2012 at 10:48:58AM +0000, Russell King - ARM Linux wrote:
>> I'd much prefer to only clear those interrupts which actually need to be
>> cleared at this point. So, I'd suggest this approach instead:
>
> Thinking about this a little more, we definitely want to mask and clear
> interrupts at probe time as well:
Acked-by: Linus Walleij <linus.walleij@linaro.org>
On the RMK-improved patch.
Thanks,
Linus Walleij
^ permalink raw reply
* [RFC PATCH] vt:tackle kbd_table
From: Alan Cox @ 2012-02-27 16:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
This could do with some extra eyes and double checking. With this one out of
the day we can start to make a dent in the console locking logic and thus
eventually into tty_lock().
From: Alan Cox <alan@linux.intel.com>
Keyboard struct lifetime is easy, but the locking is not and is completely
ignored by the existing code. Tackle this one head on
- Make the kbd_table private so we can run down all direct users
- Hoick the relevant ioctl handlers into the keyboard layer
- Lock them with the keyboard lock so they don't change mid keypress
- Add helpers for things like console stop/start so we isolate the poking
around properly
- Tweak the braille console so it still builds
There are a couple of FIXME locking cases left for ioctls that are so hideous
they should be addressed in a later patch. After this patch the kbd_table is
private and all the keyboard jiggery pokery is in one place.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/accessibility/braille/braille_console.c | 9
drivers/tty/sysrq.c | 6
drivers/tty/vt/keyboard.c | 620 ++++++++++++++++++++++-
drivers/tty/vt/selection.c | 9
drivers/tty/vt/vt.c | 27 -
drivers/tty/vt/vt_ioctl.c | 325 +-----------
include/linux/kbd_kern.h | 7
include/linux/keyboard.h | 2
include/linux/vt_kern.h | 23 +
9 files changed, 655 insertions(+), 373 deletions(-)
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index c339a08..d21167b 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -244,16 +244,13 @@ static int keyboard_notifier_call(struct notifier_block *blk,
switch (val) {
case KVAL(K_CAPS):
- on_off = vc_kbd_led(kbd_table + fg_console,
- VC_CAPSLOCK);
+ on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
break;
case KVAL(K_NUM):
- on_off = vc_kbd_led(kbd_table + fg_console,
- VC_NUMLOCK);
+ on_off = vt_get_leds(fg_console, VC_NUMLOCK);
break;
case KVAL(K_HOLD):
- on_off = vc_kbd_led(kbd_table + fg_console,
- VC_SCROLLOCK);
+ on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
break;
}
if (on_off == 1)
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 8db9125..ecb8e22 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -110,11 +110,9 @@ static struct sysrq_key_op sysrq_SAK_op = {
#ifdef CONFIG_VT
static void sysrq_handle_unraw(int key)
{
- struct kbd_struct *kbd = &kbd_table[fg_console];
-
- if (kbd)
- kbd->kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
+ vt_reset_unicode(fg_console);
}
+
static struct sysrq_key_op sysrq_unraw_op = {
.handler = sysrq_handle_unraw,
.help_msg = "unRaw",
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 0479114..8a401e6 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -67,8 +67,6 @@ extern void ctrl_alt_del(void);
#define KBD_DEFLOCK 0
-void compute_shiftstate(void);
-
/*
* Handler Tables.
*/
@@ -99,35 +97,29 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
* Variables exported for vt_ioctl.c
*/
-/* maximum values each key_handler can handle */
-const int max_vals[] = {
- 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
- NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
- 255, NR_LOCK - 1, 255, NR_BRL - 1
-};
-
-const int NR_TYPES = ARRAY_SIZE(max_vals);
-
-struct kbd_struct kbd_table[MAX_NR_CONSOLES];
-EXPORT_SYMBOL_GPL(kbd_table);
-static struct kbd_struct *kbd = kbd_table;
-
struct vt_spawn_console vt_spawn_con = {
.lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
.pid = NULL,
.sig = 0,
};
-/*
- * Variables exported for vt.c
- */
-
-int shift_state = 0;
/*
* Internal Data.
*/
+static struct kbd_struct kbd_table[MAX_NR_CONSOLES];
+static struct kbd_struct *kbd = kbd_table;
+
+/* maximum values each key_handler can handle */
+static const int max_vals[] = {
+ 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
+ NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
+ 255, NR_LOCK - 1, 255, NR_BRL - 1
+};
+
+static const int NR_TYPES = ARRAY_SIZE(max_vals);
+
static struct input_handler kbd_handler;
static DEFINE_SPINLOCK(kbd_event_lock);
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
@@ -137,6 +129,8 @@ static int npadch = -1; /* -1 or number assembled on pad */
static unsigned int diacr;
static char rep; /* flag telling character repeat */
+static int shift_state = 0;
+
static unsigned char ledstate = 0xff; /* undefined */
static unsigned char ledioctl;
@@ -187,7 +181,7 @@ static int getkeycode_helper(struct input_handle *handle, void *data)
return d->error == 0; /* stop as soon as we successfully get one */
}
-int getkeycode(unsigned int scancode)
+static int getkeycode(unsigned int scancode)
{
struct getset_keycode_data d = {
.ke = {
@@ -214,7 +208,7 @@ static int setkeycode_helper(struct input_handle *handle, void *data)
return d->error == 0; /* stop as soon as we successfully set one */
}
-int setkeycode(unsigned int scancode, unsigned int keycode)
+static int setkeycode(unsigned int scancode, unsigned int keycode)
{
struct getset_keycode_data d = {
.ke = {
@@ -382,9 +376,11 @@ static void to_utf8(struct vc_data *vc, uint c)
/*
* Called after returning from RAW mode or when changing consoles - recompute
* shift_down[] and shift_state from key_down[] maybe called when keymap is
- * undefined, so that shiftkey release is seen
+ * undefined, so that shiftkey release is seen. The caller must hold the
+ * kbd_event_lock.
*/
-void compute_shiftstate(void)
+
+static void do_compute_shiftstate(void)
{
unsigned int i, j, k, sym, val;
@@ -417,6 +413,15 @@ void compute_shiftstate(void)
}
}
+/* We still have to export this method to vt.c */
+void compute_shiftstate(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ do_compute_shiftstate();
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
+
/*
* We have a combining character DIACR here, followed by the character CH.
* If the combination occurs in the table, return the corresponding value.
@@ -636,7 +641,7 @@ static void fn_SAK(struct vc_data *vc)
static void fn_null(struct vc_data *vc)
{
- compute_shiftstate();
+ do_compute_shiftstate();
}
/*
@@ -989,6 +994,8 @@ unsigned char getledstate(void)
void setledstate(struct kbd_struct *kbd, unsigned int led)
{
+ unsigned long flags;
+ spin_lock_irqsave(&kbd_event_lock, flags);
if (!(led & ~7)) {
ledioctl = led;
kbd->ledmode = LED_SHOW_IOCTL;
@@ -996,6 +1003,7 @@ void setledstate(struct kbd_struct *kbd, unsigned int led)
kbd->ledmode = LED_SHOW_FLAGS;
set_leds();
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
}
static inline unsigned char getleds(void)
@@ -1035,6 +1043,75 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data)
return 0;
}
+/**
+ * vt_get_leds - helper for braille console
+ * @console: console to read
+ * @flag: flag we want to check
+ *
+ * Check the status of a keyboard led flag and report it back
+ */
+int vt_get_leds(int console, int flag)
+{
+ unsigned long flags;
+ struct kbd_struct * kbd = kbd_table + console;
+ int ret;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ ret = vc_kbd_led(kbd, flag);
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vt_get_leds);
+
+/**
+ * vt_set_led_state - set LED state of a console
+ * @console: console to set
+ * @leds: LED bits
+ *
+ * Set the LEDs on a console. This is a wrapper for the VT layer
+ * so that we can keep kbd knowledge internal
+ */
+void vt_set_led_state(int console, int leds)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ setledstate(kbd, leds);
+}
+
+/**
+ * vt_kbd_con_start - Keyboard side of console start
+ * @console: console
+ *
+ * Handle console start. This is a wrapper for the VT layer
+ * so that we can keep kbd knowledge internal
+ */
+void vt_kbd_con_start(int console)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ unsigned long flags;
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ clr_vc_kbd_led(kbd, VC_SCROLLOCK);
+ set_leds();
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
+
+/**
+ * vt_kbd_con_stop - Keyboard side of console stop
+ * @console: console
+ *
+ * Handle console stop. This is a wrapper for the VT layer
+ * so that we can keep kbd knowledge internal
+ */
+void vt_kbd_con_stop(int console)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ unsigned long flags;
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ set_vc_kbd_led(kbd, VC_SCROLLOCK);
+ set_leds();
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
+
/*
* This is the tasklet that updates LED state on all keyboards
* attached to the box. The reason we use tasklet is that we
@@ -1254,7 +1331,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
if (rc == NOTIFY_STOP || !key_map) {
atomic_notifier_call_chain(&keyboard_notifier_list,
KBD_UNBOUND_KEYCODE, ¶m);
- compute_shiftstate();
+ do_compute_shiftstate();
kbd->slockstate = 0;
return;
}
@@ -1614,3 +1691,494 @@ int vt_do_diacrit(unsigned int cmd, void __user *up, int perm)
}
return ret;
}
+
+/**
+ * vt_do_kdskbmode - set keyboard mode ioctl
+ * @console: the console to use
+ * @arg: the requested mode
+ *
+ * Update the keyboard mode bits while holding the correct locks.
+ * Return 0 for success or an error code.
+ */
+int vt_do_kdskbmode(int console, unsigned int arg)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ switch(arg) {
+ case K_RAW:
+ kbd->kbdmode = VC_RAW;
+ break;
+ case K_MEDIUMRAW:
+ kbd->kbdmode = VC_MEDIUMRAW;
+ break;
+ case K_XLATE:
+ kbd->kbdmode = VC_XLATE;
+ do_compute_shiftstate();
+ break;
+ case K_UNICODE:
+ kbd->kbdmode = VC_UNICODE;
+ do_compute_shiftstate();
+ break;
+ case K_OFF:
+ kbd->kbdmode = VC_OFF;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ return ret;
+}
+
+/**
+ * vt_do_kdskbmeta - set keyboard meta state
+ * @console: the console to use
+ * @arg: the requested meta state
+ *
+ * Update the keyboard meta bits while holding the correct locks.
+ * Return 0 for success or an error code.
+ */
+int vt_do_kdskbmeta(int console, unsigned int arg)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ switch(arg) {
+ case K_METABIT:
+ clr_vc_kbd_mode(kbd, VC_META);
+ break;
+ case K_ESCPREFIX:
+ set_vc_kbd_mode(kbd, VC_META);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ return ret;
+}
+
+int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
+ int perm)
+{
+ struct kbkeycode tmp;
+ int kc = 0;
+
+ if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
+ return -EFAULT;
+ switch (cmd) {
+ case KDGETKEYCODE:
+ kc = getkeycode(tmp.scancode);
+ if (kc >= 0)
+ kc = put_user(kc, &user_kbkc->keycode);
+ break;
+ case KDSETKEYCODE:
+ if (!perm)
+ return -EPERM;
+ kc = setkeycode(tmp.scancode, tmp.keycode);
+ break;
+ }
+ return kc;
+}
+
+#define i (tmp.kb_index)
+#define s (tmp.kb_table)
+#define v (tmp.kb_value)
+
+int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
+ int console)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ struct kbentry tmp;
+ ushort *key_map, *new_map, val, ov;
+ unsigned long flags;
+
+ if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
+ return -EFAULT;
+
+ if (!capable(CAP_SYS_TTY_CONFIG))
+ perm = 0;
+
+ switch (cmd) {
+ case KDGKBENT:
+ /* Ensure another thread doesn't free it under us */
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ key_map = key_maps[s];
+ if (key_map) {
+ val = U(key_map[i]);
+ if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
+ val = K_HOLE;
+ } else
+ val = (i ? K_HOLE : K_NOSUCHMAP);
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ return put_user(val, &user_kbe->kb_value);
+ case KDSKBENT:
+ if (!perm)
+ return -EPERM;
+ if (!i && v == K_NOSUCHMAP) {
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ /* deallocate map */
+ key_map = key_maps[s];
+ if (s && key_map) {
+ key_maps[s] = NULL;
+ if (key_map[0] == U(K_ALLOCATED)) {
+ kfree(key_map);
+ keymap_count--;
+ }
+ }
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ break;
+ }
+
+ if (KTYP(v) < NR_TYPES) {
+ if (KVAL(v) > max_vals[KTYP(v)])
+ return -EINVAL;
+ } else
+ if (kbd->kbdmode != VC_UNICODE)
+ return -EINVAL;
+
+ /* ++Geert: non-PC keyboards may generate keycode zero */
+#if !defined(__mc68000__) && !defined(__powerpc__)
+ /* assignment to entry 0 only tests validity of args */
+ if (!i)
+ break;
+#endif
+
+ new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ key_map = key_maps[s];
+ if (key_map == NULL) {
+ int j;
+
+ if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
+ !capable(CAP_SYS_RESOURCE)) {
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ return -EPERM;
+ }
+ key_maps[s] = new_map;
+ key_map[0] = U(K_ALLOCATED);
+ for (j = 1; j < NR_KEYS; j++)
+ key_map[j] = U(K_HOLE);
+ keymap_count++;
+ } else
+ kfree(new_map);
+
+ ov = U(key_map[i]);
+ if (v == ov)
+ goto out;
+ /*
+ * Attention Key.
+ */
+ if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ return -EPERM;
+ }
+ key_map[i] = U(v);
+ if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
+ do_compute_shiftstate();
+out:
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ break;
+ }
+ return 0;
+}
+#undef i
+#undef s
+#undef v
+
+/* FIXME: This one needs untangling and locking */
+int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
+{
+ struct kbsentry *kbs;
+ char *p;
+ u_char *q;
+ u_char __user *up;
+ int sz;
+ int delta;
+ char *first_free, *fj, *fnw;
+ int i, j, k;
+ int ret;
+
+ if (!capable(CAP_SYS_TTY_CONFIG))
+ perm = 0;
+
+ kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
+ if (!kbs) {
+ ret = -ENOMEM;
+ goto reterr;
+ }
+
+ /* we mostly copy too much here (512bytes), but who cares ;) */
+ if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
+ ret = -EFAULT;
+ goto reterr;
+ }
+ kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
+ i = kbs->kb_func;
+
+ switch (cmd) {
+ case KDGKBSENT:
+ sz = sizeof(kbs->kb_string) - 1; /* sz should have been
+ a struct member */
+ up = user_kdgkb->kb_string;
+ p = func_table[i];
+ if(p)
+ for ( ; *p && sz; p++, sz--)
+ if (put_user(*p, up++)) {
+ ret = -EFAULT;
+ goto reterr;
+ }
+ if (put_user('\0', up)) {
+ ret = -EFAULT;
+ goto reterr;
+ }
+ kfree(kbs);
+ return ((p && *p) ? -EOVERFLOW : 0);
+ case KDSKBSENT:
+ if (!perm) {
+ ret = -EPERM;
+ goto reterr;
+ }
+
+ q = func_table[i];
+ first_free = funcbufptr + (funcbufsize - funcbufleft);
+ for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
+ ;
+ if (j < MAX_NR_FUNC)
+ fj = func_table[j];
+ else
+ fj = first_free;
+
+ delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
+ if (delta <= funcbufleft) { /* it fits in current buf */
+ if (j < MAX_NR_FUNC) {
+ memmove(fj + delta, fj, first_free - fj);
+ for (k = j; k < MAX_NR_FUNC; k++)
+ if (func_table[k])
+ func_table[k] += delta;
+ }
+ if (!q)
+ func_table[i] = fj;
+ funcbufleft -= delta;
+ } else { /* allocate a larger buffer */
+ sz = 256;
+ while (sz < funcbufsize - funcbufleft + delta)
+ sz <<= 1;
+ fnw = kmalloc(sz, GFP_KERNEL);
+ if(!fnw) {
+ ret = -ENOMEM;
+ goto reterr;
+ }
+
+ if (!q)
+ func_table[i] = fj;
+ if (fj > funcbufptr)
+ memmove(fnw, funcbufptr, fj - funcbufptr);
+ for (k = 0; k < j; k++)
+ if (func_table[k])
+ func_table[k] = fnw + (func_table[k] - funcbufptr);
+
+ if (first_free > fj) {
+ memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
+ for (k = j; k < MAX_NR_FUNC; k++)
+ if (func_table[k])
+ func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
+ }
+ if (funcbufptr != func_buf)
+ kfree(funcbufptr);
+ funcbufptr = fnw;
+ funcbufleft = funcbufleft - delta + sz - funcbufsize;
+ funcbufsize = sz;
+ }
+ strcpy(func_table[i], kbs->kb_string);
+ break;
+ }
+ ret = 0;
+reterr:
+ kfree(kbs);
+ return ret;
+}
+
+int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ unsigned long flags;
+ unsigned char ucval;
+
+ switch(cmd) {
+ /* the ioctls below read/set the flags usually shown in the leds */
+ /* don't use them - they will go away without warning */
+ case KDGKBLED:
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ return put_user(ucval, (char __user *)arg);
+
+ case KDSKBLED:
+ if (!perm)
+ return -EPERM;
+ if (arg & ~0x77)
+ return -EINVAL;
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ kbd->ledflagstate = (arg & 7);
+ kbd->default_ledflagstate = ((arg >> 4) & 7);
+ set_leds();
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+ break;
+
+ /* the ioctls below only set the lights, not the functions */
+ /* for those, see KDGKBLED and KDSKBLED above */
+ case KDGETLED:
+ ucval = getledstate();
+ return put_user(ucval, (char __user *)arg);
+
+ case KDSETLED:
+ if (!perm)
+ return -EPERM;
+ setledstate(kbd, arg);
+ return 0;
+ }
+ return -ENOIOCTLCMD;
+}
+
+int vt_do_kdgkbmode(int console)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ /* This is a spot read so needs no locking */
+ switch (kbd->kbdmode) {
+ case VC_RAW:
+ return K_RAW;
+ case VC_MEDIUMRAW:
+ return K_MEDIUMRAW;
+ case VC_UNICODE:
+ return K_UNICODE;
+ case VC_OFF:
+ return K_OFF;
+ default:
+ return K_XLATE;
+ }
+}
+
+/**
+ * vt_do_kdgkbmeta - report meta status
+ * @console: console to report
+ *
+ * Report the meta flag status of this console
+ */
+int vt_do_kdgkbmeta(int console)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ /* Again a spot read so no locking */
+ return vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT;
+}
+
+/**
+ * vt_reset_unicode - reset the unicode status
+ * @console: console being reset
+ *
+ * Restore the unicode console state to its default
+ */
+void vt_reset_unicode(int console)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
+
+/**
+ * vt_get_shiftstate - shift bit state
+ *
+ * Report the shift bits from the keyboard state. We have to export
+ * this to support some oddities in the vt layer.
+ */
+int vt_get_shift_state(void)
+{
+ /* Don't lock as this is a transient report */
+ return shift_state;
+}
+
+/**
+ * vt_reset_keyboard - reset keyboard state
+ * @console: console to reset
+ *
+ * Reset the keyboard bits for a console as part of a general console
+ * reset event
+ */
+void vt_reset_keyboard(int console)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ set_vc_kbd_mode(kbd, VC_REPEAT);
+ clr_vc_kbd_mode(kbd, VC_CKMODE);
+ clr_vc_kbd_mode(kbd, VC_APPLIC);
+ clr_vc_kbd_mode(kbd, VC_CRLF);
+ kbd->lockstate = 0;
+ kbd->slockstate = 0;
+ kbd->ledmode = LED_SHOW_FLAGS;
+ kbd->ledflagstate = kbd->default_ledflagstate;
+ /* do not do set_leds here because this causes an endless tasklet loop
+ when the keyboard hasn't been initialized yet */
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
+
+/**
+ * vt_get_kbd_mode_bit - read keyboard status bits
+ * @console: console to read from
+ * @bit: mode bit to read
+ *
+ * Report back a vt mode bit. We do this without locking so the
+ * caller must be sure that there are no synchronization needs
+ */
+
+int vt_get_kbd_mode_bit(int console, int bit)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ return vc_kbd_mode(kbd, bit);
+}
+
+/**
+ * vt_set_kbd_mode_bit - read keyboard status bits
+ * @console: console to read from
+ * @bit: mode bit to read
+ *
+ * Set a vt mode bit. We do this without locking so the
+ * caller must be sure that there are no synchronization needs
+ */
+
+void vt_set_kbd_mode_bit(int console, int bit)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ set_vc_kbd_mode(kbd, bit);
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
+
+/**
+ * vt_clr_kbd_mode_bit - read keyboard status bits
+ * @console: console to read from
+ * @bit: mode bit to read
+ *
+ * Report back a vt mode bit. We do this without locking so the
+ * caller must be sure that there are no synchronization needs
+ */
+
+void vt_clr_kbd_mode_bit(int console, int bit)
+{
+ struct kbd_struct * kbd = kbd_table + console;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_event_lock, flags);
+ clr_vc_kbd_mode(kbd, bit);
+ spin_unlock_irqrestore(&kbd_event_lock, flags);
+}
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 7a0a12a..738e45a 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -30,6 +30,7 @@
extern void poke_blanked_console(void);
+/* FIXME: all this needs locking */
/* Variables for selection control. */
/* Use a dynamic buffer, instead of static (Dec 1994) */
struct vc_data *sel_cons; /* must not be deallocated */
@@ -138,7 +139,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
- struct kbd_struct *kbd = kbd_table + fg_console;
+ int mode;
poke_blanked_console();
@@ -182,7 +183,11 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
clear_selection();
sel_cons = vc_cons[fg_console].d;
}
- use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
+ mode = vt_do_kdgkbmode(fg_console);
+ if (mode == K_UNICODE)
+ use_unicode = 1;
+ else
+ use_unicode = 0;
switch (sel_mode)
{
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 3c7c56b..8205578 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1028,9 +1028,9 @@ void vc_deallocate(unsigned int currcons)
* VT102 emulator
*/
-#define set_kbd(vc, x) set_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
-#define clr_kbd(vc, x) clr_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
-#define is_kbd(vc, x) vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
+#define set_kbd(vc, x) vt_set_kbd_mode_bit((vc)->vc_num, (x))
+#define clr_kbd(vc, x) vt_clr_kbd_mode_bit((vc)->vc_num, (x))
+#define is_kbd(vc, x) vt_get_kbd_mode_bit((vc)->vc_num, (x))
#define decarm VC_REPEAT
#define decckm VC_CKMODE
@@ -1652,16 +1652,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
vc->vc_deccm = global_cursor_default;
vc->vc_decim = 0;
- set_kbd(vc, decarm);
- clr_kbd(vc, decckm);
- clr_kbd(vc, kbdapplic);
- clr_kbd(vc, lnm);
- kbd_table[vc->vc_num].lockstate = 0;
- kbd_table[vc->vc_num].slockstate = 0;
- kbd_table[vc->vc_num].ledmode = LED_SHOW_FLAGS;
- kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate;
- /* do not do set_leds here because this causes an endless tasklet loop
- when the keyboard hasn't been initialized yet */
+ vt_reset_keyboard(vc->vc_num);
vc->vc_cursor_type = cur_default;
vc->vc_complement_mask = vc->vc_s_complement_mask;
@@ -1979,7 +1970,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
case 'q': /* DECLL - but only 3 leds */
/* map 0,1,2,3 to 0,1,2,4 */
if (vc->vc_par[0] < 4)
- setledstate(kbd_table + vc->vc_num,
+ vt_set_led_state(vc->vc_num,
(vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
return;
case 'r':
@@ -2642,7 +2633,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
* kernel-internal variable; programs not closely
* related to the kernel should not use this.
*/
- data = shift_state;
+ data = vt_get_shift_state();
ret = __put_user(data, p);
break;
case TIOCL_GETMOUSEREPORTING:
@@ -2753,8 +2744,7 @@ static void con_stop(struct tty_struct *tty)
console_num = tty->index;
if (!vc_cons_allocated(console_num))
return;
- set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
- set_leds();
+ vt_kbd_con_stop(console_num);
}
/*
@@ -2768,8 +2758,7 @@ static void con_start(struct tty_struct *tty)
console_num = tty->index;
if (!vc_cons_allocated(console_num))
return;
- clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
- set_leds();
+ vt_kbd_con_start(console_num);
}
static void con_flush_chars(struct tty_struct *tty)
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 80af0f9..28ca0aa 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -195,232 +195,7 @@ int vt_waitactive(int n)
#define GPLAST 0x3df
#define GPNUM (GPLAST - GPFIRST + 1)
-#define i (tmp.kb_index)
-#define s (tmp.kb_table)
-#define v (tmp.kb_value)
-static inline int
-do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd)
-{
- struct kbentry tmp;
- ushort *key_map, val, ov;
-
- if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
- return -EFAULT;
-
- if (!capable(CAP_SYS_TTY_CONFIG))
- perm = 0;
-
- switch (cmd) {
- case KDGKBENT:
- key_map = key_maps[s];
- if (key_map) {
- val = U(key_map[i]);
- if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
- val = K_HOLE;
- } else
- val = (i ? K_HOLE : K_NOSUCHMAP);
- return put_user(val, &user_kbe->kb_value);
- case KDSKBENT:
- if (!perm)
- return -EPERM;
- if (!i && v == K_NOSUCHMAP) {
- /* deallocate map */
- key_map = key_maps[s];
- if (s && key_map) {
- key_maps[s] = NULL;
- if (key_map[0] == U(K_ALLOCATED)) {
- kfree(key_map);
- keymap_count--;
- }
- }
- break;
- }
-
- if (KTYP(v) < NR_TYPES) {
- if (KVAL(v) > max_vals[KTYP(v)])
- return -EINVAL;
- } else
- if (kbd->kbdmode != VC_UNICODE)
- return -EINVAL;
-
- /* ++Geert: non-PC keyboards may generate keycode zero */
-#if !defined(__mc68000__) && !defined(__powerpc__)
- /* assignment to entry 0 only tests validity of args */
- if (!i)
- break;
-#endif
-
- if (!(key_map = key_maps[s])) {
- int j;
-
- if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
- !capable(CAP_SYS_RESOURCE))
- return -EPERM;
-
- key_map = kmalloc(sizeof(plain_map),
- GFP_KERNEL);
- if (!key_map)
- return -ENOMEM;
- key_maps[s] = key_map;
- key_map[0] = U(K_ALLOCATED);
- for (j = 1; j < NR_KEYS; j++)
- key_map[j] = U(K_HOLE);
- keymap_count++;
- }
- ov = U(key_map[i]);
- if (v == ov)
- break; /* nothing to do */
- /*
- * Attention Key.
- */
- if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- key_map[i] = U(v);
- if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
- compute_shiftstate();
- break;
- }
- return 0;
-}
-#undef i
-#undef s
-#undef v
-
-static inline int
-do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm)
-{
- struct kbkeycode tmp;
- int kc = 0;
-
- if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
- return -EFAULT;
- switch (cmd) {
- case KDGETKEYCODE:
- kc = getkeycode(tmp.scancode);
- if (kc >= 0)
- kc = put_user(kc, &user_kbkc->keycode);
- break;
- case KDSETKEYCODE:
- if (!perm)
- return -EPERM;
- kc = setkeycode(tmp.scancode, tmp.keycode);
- break;
- }
- return kc;
-}
-
-static inline int
-do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
-{
- struct kbsentry *kbs;
- char *p;
- u_char *q;
- u_char __user *up;
- int sz;
- int delta;
- char *first_free, *fj, *fnw;
- int i, j, k;
- int ret;
-
- if (!capable(CAP_SYS_TTY_CONFIG))
- perm = 0;
-
- kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
- if (!kbs) {
- ret = -ENOMEM;
- goto reterr;
- }
-
- /* we mostly copy too much here (512bytes), but who cares ;) */
- if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
- ret = -EFAULT;
- goto reterr;
- }
- kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
- i = kbs->kb_func;
-
- switch (cmd) {
- case KDGKBSENT:
- sz = sizeof(kbs->kb_string) - 1; /* sz should have been
- a struct member */
- up = user_kdgkb->kb_string;
- p = func_table[i];
- if(p)
- for ( ; *p && sz; p++, sz--)
- if (put_user(*p, up++)) {
- ret = -EFAULT;
- goto reterr;
- }
- if (put_user('\0', up)) {
- ret = -EFAULT;
- goto reterr;
- }
- kfree(kbs);
- return ((p && *p) ? -EOVERFLOW : 0);
- case KDSKBSENT:
- if (!perm) {
- ret = -EPERM;
- goto reterr;
- }
- q = func_table[i];
- first_free = funcbufptr + (funcbufsize - funcbufleft);
- for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
- ;
- if (j < MAX_NR_FUNC)
- fj = func_table[j];
- else
- fj = first_free;
-
- delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
- if (delta <= funcbufleft) { /* it fits in current buf */
- if (j < MAX_NR_FUNC) {
- memmove(fj + delta, fj, first_free - fj);
- for (k = j; k < MAX_NR_FUNC; k++)
- if (func_table[k])
- func_table[k] += delta;
- }
- if (!q)
- func_table[i] = fj;
- funcbufleft -= delta;
- } else { /* allocate a larger buffer */
- sz = 256;
- while (sz < funcbufsize - funcbufleft + delta)
- sz <<= 1;
- fnw = kmalloc(sz, GFP_KERNEL);
- if(!fnw) {
- ret = -ENOMEM;
- goto reterr;
- }
-
- if (!q)
- func_table[i] = fj;
- if (fj > funcbufptr)
- memmove(fnw, funcbufptr, fj - funcbufptr);
- for (k = 0; k < j; k++)
- if (func_table[k])
- func_table[k] = fnw + (func_table[k] - funcbufptr);
-
- if (first_free > fj) {
- memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
- for (k = j; k < MAX_NR_FUNC; k++)
- if (func_table[k])
- func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
- }
- if (funcbufptr != func_buf)
- kfree(funcbufptr);
- funcbufptr = fnw;
- funcbufleft = funcbufleft - delta + sz - funcbufsize;
- funcbufsize = sz;
- }
- strcpy(func_table[i], kbs->kb_string);
- break;
- }
- ret = 0;
-reterr:
- kfree(kbs);
- return ret;
-}
static inline int
do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
@@ -497,7 +272,6 @@ int vt_ioctl(struct tty_struct *tty,
{
struct vc_data *vc = tty->driver_data;
struct console_font_op op; /* used in multiple places here */
- struct kbd_struct * kbd;
unsigned int console;
unsigned char ucval;
unsigned int uival;
@@ -523,7 +297,6 @@ int vt_ioctl(struct tty_struct *tty,
if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
perm = 1;
- kbd = kbd_table + console;
switch (cmd) {
case TIOCLINUX:
ret = tioclinux(tty, arg);
@@ -565,7 +338,8 @@ int vt_ioctl(struct tty_struct *tty,
* this is naive.
*/
ucval = KB_101;
- goto setchar;
+ ret = put_user(ucval, (char __user *)arg);
+ break;
/*
* These cannot be implemented on any machine that implements
@@ -670,68 +444,25 @@ int vt_ioctl(struct tty_struct *tty,
case KDSKBMODE:
if (!perm)
goto eperm;
- switch(arg) {
- case K_RAW:
- kbd->kbdmode = VC_RAW;
- break;
- case K_MEDIUMRAW:
- kbd->kbdmode = VC_MEDIUMRAW;
- break;
- case K_XLATE:
- kbd->kbdmode = VC_XLATE;
- compute_shiftstate();
- break;
- case K_UNICODE:
- kbd->kbdmode = VC_UNICODE;
- compute_shiftstate();
- break;
- case K_OFF:
- kbd->kbdmode = VC_OFF;
- break;
- default:
- ret = -EINVAL;
- goto out;
- }
- tty_ldisc_flush(tty);
+ ret = vt_do_kdskbmode(console, arg);
+ if (ret == 0)
+ tty_ldisc_flush(tty);
break;
case KDGKBMODE:
- switch (kbd->kbdmode) {
- case VC_RAW:
- uival = K_RAW;
- break;
- case VC_MEDIUMRAW:
- uival = K_MEDIUMRAW;
- break;
- case VC_UNICODE:
- uival = K_UNICODE;
- break;
- case VC_OFF:
- uival = K_OFF;
- break;
- default:
- uival = K_XLATE;
- break;
- }
- goto setint;
+ uival = vt_do_kdgkbmode(console);
+ ret = put_user(uival, (int __user *)arg);
+ break;
/* this could be folded into KDSKBMODE, but for compatibility
reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
case KDSKBMETA:
- switch(arg) {
- case K_METABIT:
- clr_vc_kbd_mode(kbd, VC_META);
- break;
- case K_ESCPREFIX:
- set_vc_kbd_mode(kbd, VC_META);
- break;
- default:
- ret = -EINVAL;
- }
+ ret = vt_do_kdskbmeta(console, arg);
break;
case KDGKBMETA:
- uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
+ /* FIXME: should review whether this is worth locking */
+ uival = vt_do_kdgkbmeta(console);
setint:
ret = put_user(uival, (int __user *)arg);
break;
@@ -740,17 +471,17 @@ int vt_ioctl(struct tty_struct *tty,
case KDSETKEYCODE:
if(!capable(CAP_SYS_TTY_CONFIG))
perm = 0;
- ret = do_kbkeycode_ioctl(cmd, up, perm);
+ ret = vt_do_kbkeycode_ioctl(cmd, up, perm);
break;
case KDGKBENT:
case KDSKBENT:
- ret = do_kdsk_ioctl(cmd, up, perm, kbd);
+ ret = vt_do_kdsk_ioctl(cmd, up, perm, console);
break;
case KDGKBSENT:
case KDSKBSENT:
- ret = do_kdgkb_ioctl(cmd, up, perm);
+ ret = vt_do_kdgkb_ioctl(cmd, up, perm);
break;
/* Diacritical processing. Handled in keyboard.c as it has
@@ -765,33 +496,10 @@ int vt_ioctl(struct tty_struct *tty,
/* the ioctls below read/set the flags usually shown in the leds */
/* don't use them - they will go away without warning */
case KDGKBLED:
- ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
- goto setchar;
-
case KDSKBLED:
- if (!perm)
- goto eperm;
- if (arg & ~0x77) {
- ret = -EINVAL;
- break;
- }
- kbd->ledflagstate = (arg & 7);
- kbd->default_ledflagstate = ((arg >> 4) & 7);
- set_leds();
- break;
-
- /* the ioctls below only set the lights, not the functions */
- /* for those, see KDGKBLED and KDSKBLED above */
case KDGETLED:
- ucval = getledstate();
- setchar:
- ret = put_user(ucval, (char __user *)arg);
- break;
-
case KDSETLED:
- if (!perm)
- goto eperm;
- setledstate(kbd, arg);
+ ret = vt_do_kdskled(console, cmd, arg, perm);
break;
/*
@@ -1286,7 +994,7 @@ eperm:
void reset_vc(struct vc_data *vc)
{
vc->vc_mode = KD_TEXT;
- kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
+ vt_reset_unicode(vc->vc_num);
vc->vt_mode.mode = VT_AUTO;
vc->vt_mode.waitv = 0;
vc->vt_mode.relsig = 0;
@@ -1309,6 +1017,7 @@ void vc_SAK(struct work_struct *work)
console_lock();
vc = vc_con->d;
if (vc) {
+ /* FIXME: review tty ref counting */
tty = vc->port.tty;
/*
* SAK should also work in all raw modes and reset
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index ec2d17b..daf4a3a 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -7,8 +7,6 @@
extern struct tasklet_struct keyboard_tasklet;
-extern int shift_state;
-
extern char *func_table[MAX_NR_FUNC];
extern char func_buf[];
extern char *funcbufptr;
@@ -65,8 +63,6 @@ struct kbd_struct {
#define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */
};
-extern struct kbd_struct kbd_table[];
-
extern int kbd_init(void);
extern unsigned char getledstate(void);
@@ -79,6 +75,7 @@ extern void (*kbd_ledfunc)(unsigned int led);
extern int set_console(int nr);
extern void schedule_console_callback(void);
+/* FIXME: review locking for vt.c callers */
static inline void set_leds(void)
{
tasklet_schedule(&keyboard_tasklet);
@@ -142,8 +139,6 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
struct console;
-int getkeycode(unsigned int scancode);
-int setkeycode(unsigned int scancode, unsigned int keycode);
void compute_shiftstate(void);
/* defkeymap.c */
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index 33a63f6..86e5214 100644
--- a/include/linux/keyboard.h
+++ b/include/linux/keyboard.h
@@ -24,8 +24,6 @@
#ifdef __KERNEL__
struct notifier_block;
-extern const int NR_TYPES;
-extern const int max_vals[];
extern unsigned short *key_maps[MAX_NR_KEYMAPS];
extern unsigned short plain_map[NR_KEYS];
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 5d8726a..e33d77f 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -169,5 +169,28 @@ extern void hide_boot_cursor(bool hide);
/* keyboard provided interfaces */
extern int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm);
+extern int vt_do_kdskbmode(int console, unsigned int arg);
+extern int vt_do_kdskbmeta(int console, unsigned int arg);
+extern int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
+ int perm);
+extern int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe,
+ int perm, int console);
+extern int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb,
+ int perm);
+extern int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm);
+extern int vt_do_kdgkbmode(int console);
+extern int vt_do_kdgkbmeta(int console);
+extern void vt_reset_unicode(int console);
+extern int vt_get_shift_state(void);
+extern void vt_reset_keyboard(int console);
+extern int vt_get_leds(int console, int flag);
+extern int vt_get_kbd_mode_bit(int console, int bit);
+extern void vt_set_kbd_mode_bit(int console, int bit);
+extern void vt_clr_kbd_mode_bit(int console, int bit);
+extern void vt_set_led_state(int console, int leds);
+extern void vt_set_led_state(int console, int leds);
+extern void vt_kbd_con_start(int console);
+extern void vt_kbd_con_stop(int console);
+
#endif /* _VT_KERN_H */
^ 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