* Re: [PATCH 2/2] tty: serial core: use the ACPI PM state defines
From: Alan Cox @ 2012-12-06 19:31 UTC (permalink / raw)
To: Linus Walleij
Cc: linux-serial, Greg Kroah-Hartman, Len Brown, Rafael J. Wysocki,
Rickard Andersson, linux-acpi, Linus Walleij
In-Reply-To: <1354819612-2401-1-git-send-email-linus.walleij@stericsson.com>
On Thu, 6 Dec 2012 19:46:52 +0100
Linus Walleij <linus.walleij@stericsson.com> wrote:
> From: Linus Walleij <linus.walleij@linaro.org>
>
> The Documentation/serial/driver file defines that:
>
> State indicates the new state (defined by ACPI D0-D3),
> oldstate indicates the previous state. Essentially, D0
> means fully on, D3 means powered down.
>
> So let's change the code to actually using the defined ACPI
> states instead of using magic numbers.
The "magic numbers" being "1" to mean one, "2" to mean two etc..
Almost none of the platforms using the serial driver even have ACPI so
this seems to be an obfuscation of a simple numbering system for a
subsystem specific set of definitions that may or may not fit in future.
What are you going to do if it turns out serial ports on some platform
have a state that doesn't fit ACPI_STATE_foo because its got a
behaviour that isn't in the ACPI specification ?
This seems to be tying stuff together in a way that will just cause
future pain.
Alan
^ permalink raw reply
* Re: [PATCH 2/2] tty: serial core: use the ACPI PM state defines
From: Linus Walleij @ 2012-12-06 19:31 UTC (permalink / raw)
To: Alan Cox
Cc: Linus Walleij, linux-serial, Greg Kroah-Hartman, Len Brown,
Rafael J. Wysocki, Rickard Andersson, linux-acpi
In-Reply-To: <20121206193131.33823e02@bob.linux.org.uk>
On Thu, Dec 6, 2012 at 8:31 PM, Alan Cox <alan@linux.intel.com> wrote:
> Almost none of the platforms using the serial driver even have ACPI so
> this seems to be an obfuscation of a simple numbering system for a
> subsystem specific set of definitions that may or may not fit in future.
OK so we need to get away from using the ACPI numbering scheme.
What about we define something in the <linux/tty.h> file instead
and delete the paragraph from the documentation saying it is related
to ACPI? (Will try this next.)
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 2/2] tty: serial core: use the ACPI PM state defines
From: Linus Walleij @ 2012-12-06 18:46 UTC (permalink / raw)
To: linux-serial, Greg Kroah-Hartman, Len Brown, Rafael J. Wysocki
Cc: Alan Cox, Rickard Andersson, linux-acpi, Linus Walleij
From: Linus Walleij <linus.walleij@linaro.org>
The Documentation/serial/driver file defines that:
State indicates the new state (defined by ACPI D0-D3),
oldstate indicates the previous state. Essentially, D0
means fully on, D3 means powered down.
So let's change the code to actually using the defined ACPI
states instead of using magic numbers. Further it is clear
from the ACPI definitions that the state is a u8 so use this
data type.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/tty/serial/serial_core.c | 26 ++++++++++++++------------
include/linux/serial_core.h | 2 +-
2 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 2c7230a..f327115 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,6 +34,8 @@
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <acpi/acstates.h> /* for power states */
+
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -59,7 +61,7 @@ static struct lock_class_key port_lock_key;
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
-static void uart_change_pm(struct uart_state *state, int pm_state);
+static void uart_change_pm(struct uart_state *state, u8 pm_state);
static void uart_port_shutdown(struct tty_port *port);
@@ -1365,7 +1367,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
spin_lock_irqsave(&port->lock, flags);
} else if (!uart_console(uport)) {
spin_unlock_irqrestore(&port->lock, flags);
- uart_change_pm(state, 3);
+ uart_change_pm(state, ACPI_STATE_D3_HOT);
spin_lock_irqsave(&port->lock, flags);
}
@@ -1579,7 +1581,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
* Make sure the device is in D0 state.
*/
if (port->count == 1)
- uart_change_pm(state, 0);
+ uart_change_pm(state, ACPI_STATE_D0);
/*
* Start up the serial port.
@@ -1620,7 +1622,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
{
struct uart_state *state = drv->state + i;
struct tty_port *port = &state->port;
- int pm_state;
+ u8 pm_state;
struct uart_port *uport = state->uart_port;
char stat_buf[32];
unsigned int status;
@@ -1646,7 +1648,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
mutex_lock(&port->mutex);
pm_state = state->pm_state;
if (pm_state)
- uart_change_pm(state, 0);
+ uart_change_pm(state, ACPI_STATE_D0);
spin_lock_irq(&uport->lock);
status = uport->ops->get_mctrl(uport);
spin_unlock_irq(&uport->lock);
@@ -1897,7 +1899,7 @@ EXPORT_SYMBOL_GPL(uart_set_options);
*
* Locking: port->mutex has to be held
*/
-static void uart_change_pm(struct uart_state *state, int pm_state)
+static void uart_change_pm(struct uart_state *state, u8 pm_state)
{
struct uart_port *port = state->uart_port;
@@ -1982,7 +1984,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
console_stop(uport->cons);
if (console_suspend_enabled || !uart_console(uport))
- uart_change_pm(state, 3);
+ uart_change_pm(state, ACPI_STATE_D3_HOT);
mutex_unlock(&port->mutex);
@@ -2027,7 +2029,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
termios = port->tty->termios;
if (console_suspend_enabled)
- uart_change_pm(state, 0);
+ uart_change_pm(state, ACPI_STATE_D0);
uport->ops->set_termios(uport, &termios, NULL);
if (console_suspend_enabled)
console_start(uport->cons);
@@ -2037,7 +2039,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
const struct uart_ops *ops = uport->ops;
int ret;
- uart_change_pm(state, 0);
+ uart_change_pm(state, ACPI_STATE_D0);
spin_lock_irq(&uport->lock);
ops->set_mctrl(uport, 0);
spin_unlock_irq(&uport->lock);
@@ -2137,7 +2139,7 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
uart_report_port(drv, port);
/* Power up port for set_mctrl() */
- uart_change_pm(state, 0);
+ uart_change_pm(state, ACPI_STATE_D0);
/*
* Ensure that the modem control lines are de-activated.
@@ -2161,7 +2163,7 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
* console if we have one.
*/
if (!uart_console(port))
- uart_change_pm(state, 3);
+ uart_change_pm(state, ACPI_STATE_D3_HOT);
}
}
@@ -2588,7 +2590,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
}
state->uart_port = uport;
- state->pm_state = -1;
+ state->pm_state = ACPI_STATE_UNKNOWN;
uport->cons = drv->cons;
uport->state = state;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index c6690a2..43e8d87 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -214,7 +214,7 @@ static inline void serial_port_out(struct uart_port *up, int offset, int value)
struct uart_state {
struct tty_port port;
- int pm_state;
+ u8 pm_state;
struct circ_buf xmit;
struct uart_port *uart_port;
--
1.7.11.3
^ permalink raw reply related
* [PATCH 1/2] ACPI: break out the states from the ACPI types
From: Linus Walleij @ 2012-12-06 18:46 UTC (permalink / raw)
To: linux-serial, Greg Kroah-Hartman, Len Brown, Rafael J. Wysocki
Cc: Alan Cox, Rickard Andersson, linux-acpi, Linus Walleij
From: Linus Walleij <linus.walleij@linaro.org>
The ACPI states are used by the serial core by way of magic numbers
in the code, it's pretty confusing, so we need to reference the
definitions from the actual ACPI includes.
This breaks out the state definitons. The entire <acpi/actypes.h>
include can not be used since that file will not compile for a
machine that is not using ACPI due to things like this:
#ifndef ACPI_MACHINE_WIDTH
#error ACPI_MACHINE_WIDTH not defined
#endif
So just break it out, include it back into the original file and
be done with it. After this the serial core can piggyback the
actual state definitions from the ACPI subsystem.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
include/acpi/acstates.h | 32 ++++++++++++++++++++++++++++++++
include/acpi/actypes.h | 32 ++------------------------------
2 files changed, 34 insertions(+), 30 deletions(-)
create mode 100644 include/acpi/acstates.h
diff --git a/include/acpi/acstates.h b/include/acpi/acstates.h
new file mode 100644
index 0000000..fe73f6c
--- /dev/null
+++ b/include/acpi/acstates.h
@@ -0,0 +1,32 @@
+/*
+ * Power state values
+ *
+ * These defines are used by subsystems that are not necessarily
+ * tied in to using ACPI.
+ */
+#define ACPI_STATE_UNKNOWN (u8) 0xFF
+
+#define ACPI_STATE_S0 (u8) 0
+#define ACPI_STATE_S1 (u8) 1
+#define ACPI_STATE_S2 (u8) 2
+#define ACPI_STATE_S3 (u8) 3
+#define ACPI_STATE_S4 (u8) 4
+#define ACPI_STATE_S5 (u8) 5
+#define ACPI_S_STATES_MAX ACPI_STATE_S5
+#define ACPI_S_STATE_COUNT 6
+
+#define ACPI_STATE_D0 (u8) 0
+#define ACPI_STATE_D1 (u8) 1
+#define ACPI_STATE_D2 (u8) 2
+#define ACPI_STATE_D3_HOT (u8) 3
+#define ACPI_STATE_D3 (u8) 4
+#define ACPI_STATE_D3_COLD ACPI_STATE_D3
+#define ACPI_D_STATES_MAX ACPI_STATE_D3
+#define ACPI_D_STATE_COUNT 5
+
+#define ACPI_STATE_C0 (u8) 0
+#define ACPI_STATE_C1 (u8) 1
+#define ACPI_STATE_C2 (u8) 2
+#define ACPI_STATE_C3 (u8) 3
+#define ACPI_C_STATES_MAX ACPI_STATE_C3
+#define ACPI_C_STATE_COUNT 4
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 4f43f1f..29d6c46 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -44,6 +44,8 @@
#ifndef __ACTYPES_H__
#define __ACTYPES_H__
+#include "acstates.h"
+
/* acpisrc:struct_defs -- for acpisrc conversion */
/*
@@ -487,36 +489,6 @@ typedef u64 acpi_integer;
#define ACPI_INITIALIZED_OK 0x02
/*
- * Power state values
- */
-#define ACPI_STATE_UNKNOWN (u8) 0xFF
-
-#define ACPI_STATE_S0 (u8) 0
-#define ACPI_STATE_S1 (u8) 1
-#define ACPI_STATE_S2 (u8) 2
-#define ACPI_STATE_S3 (u8) 3
-#define ACPI_STATE_S4 (u8) 4
-#define ACPI_STATE_S5 (u8) 5
-#define ACPI_S_STATES_MAX ACPI_STATE_S5
-#define ACPI_S_STATE_COUNT 6
-
-#define ACPI_STATE_D0 (u8) 0
-#define ACPI_STATE_D1 (u8) 1
-#define ACPI_STATE_D2 (u8) 2
-#define ACPI_STATE_D3_HOT (u8) 3
-#define ACPI_STATE_D3 (u8) 4
-#define ACPI_STATE_D3_COLD ACPI_STATE_D3
-#define ACPI_D_STATES_MAX ACPI_STATE_D3
-#define ACPI_D_STATE_COUNT 5
-
-#define ACPI_STATE_C0 (u8) 0
-#define ACPI_STATE_C1 (u8) 1
-#define ACPI_STATE_C2 (u8) 2
-#define ACPI_STATE_C3 (u8) 3
-#define ACPI_C_STATES_MAX ACPI_STATE_C3
-#define ACPI_C_STATE_COUNT 4
-
-/*
* Sleep type invalid value
*/
#define ACPI_SLEEP_TYPE_MAX 0x7
--
1.7.11.3
^ permalink raw reply related
* Re: [RFC PATCH 1/3] UART: Add UART subsystem as a bus.
From: Alan Cox @ 2012-12-06 13:53 UTC (permalink / raw)
To: Zheng, Lv
Cc: Mika Westerberg, Alan Cox, Brown, Len, Wysocki, Rafael J,
Greg Kroah-Hartman, linux-acpi@vger.kernel.org,
linux-serial@vger.kernel.org, Heikki Krogerus, Mathias Nyman,
Huang, Ying
In-Reply-To: <1AE640813FDE7649BE1B193DEA596E88BD6C94@SHSMSX101.ccr.corp.intel.com>
> > We just need a set of type names for the sysfs node I think "bluetooth", "ups",
> > "loconet", "serial", "modem", "cir" etc...
>
> Is it a good idea to introduce uart_device driver in the kernel to fill a new 'ldisc' member in the uart_device or to load ldisc by default for the corresponding tty_port?
No but it can provide information to help user space. In many cases the
decision isn't about a line discipline but about automatically setting
permissions or linking ports to the right driver.
The hints need to be generic - they can come from open firmware, from pci
identifiers, from ACPI and so on.
> Shall we change the uart_bus to the tty_bus, then introduce tty_host / tty_target for the bus?
We have a tty class - is that not sufficient ?
Alan
^ permalink raw reply
* Re: [RFC PATCH v3 1/4] UART: Add UART subsystem as a bus.
From: Alan Cox @ 2012-12-06 13:40 UTC (permalink / raw)
To: Lv Zheng
Cc: Len Brown, Rafael J Wysocki, Greg Kroah-Hartman, Mika Westerberg,
linux-acpi, linux-serial
In-Reply-To: <c561ccd12ef845a7f30f26dfb706bb569e7244a7.1354785372.git.lv.zheng@intel.com>
> enumerated and userspace can obtain the hotplug event of the UART
> target devices. Linux kernel is lack of an overall enumeration
> mechanism for UART target devices.
ls /sys/class/tty/
> In order to send uevent, a device need to be a class device or a bus
> device. This patch introduces a bus_type subsystem to manage the new
I still don't see why the existing tty class interfaces cannot be used,
the hints from ACPI (or anywhere else) cannot be attached as properties
to the tty driver and device sysfs
Alan
^ permalink raw reply
* [RFC PATCH v3 4/4] UART: Add dummy devices to test the enumeration.
From: Lv Zheng @ 2012-12-06 9:22 UTC (permalink / raw)
To: Len Brown, Rafael J Wysocki, Greg Kroah-Hartman, Alan Cox,
Mika Westerberg
Cc: linux-acpi, linux-serial, Lv Zheng
In-Reply-To: <cover.1354785372.git.lv.zheng@intel.com>
This is a test patch that should not be merged to any of the published
Linux source tree.
1. The result of the UART dummy target device is as follows:
# udevadm monitor --kernel --environment > ~/uart.uevents
# echo add > /sys/bus/uart/uevent
# echo add > /sys/bus/uart/devices/DUMMY/uevent
# cat ~/uart.uevents
monitor will print the received events for:
KERNEL - the kernel uevent
KERNEL[252.443458] add /bus/uart (bus)
ACTION=add
DEVPATH=/bus/uart
SEQNUM=1142
SUBSYSTEM=bus
KERNEL[268.491709] add /devices/platform/serial8250/DUMMY (uart)
ACTION=add
DEVPATH=/devices/platform/serial8250/DUMMY
DEVTYPE=uart_device
MODALIAS=uart:DUMMY
SEQNUM=1144
SUBSYSTEM=uart
# cat /sys/bus/uart/devices/DUMMY/modalias
uart:DUMMY
# cat /sys/bus/uart/devices/DUMMY/tty_dev
ttyS3
# cat /sys/bus/uart/devices/DUMMY/tty_attrs
115200 8N1 HW SW
# cat /sys/bus/uart/devices/DUMMY/modem_lines
LE:RTS,
# ls -l /sys/bus/uart/devices/
DUMMY -> ../../../devices/platform/serial8250/DUMMY
# ls -l /sys/devices/platform/serial8250/DUMMY/
subsystem -> ../../../../bus/uart
host_node -> ../tty/ttyS3
# ls -l /sys/devices/platform/serial8250/tty/ttyS3/
target_node -> ../../DUMMY
2. The result of the UART customized DSDT target device is as follows:
The test is based on the following customized DSDT (containing the dummy
uart host adapter INTF000 and target device INTF001):
Device (UA00)
{
Name (_HID, "INTF000") // _HID: Hardware ID
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0x00000000, // Address Base
0x00001000) // Address Length
})
Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Return (RBUF)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Device (BTH0)
{
Name (_HID, "INTF001") // _HID: Hardware ID
Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Name (UBUF, ResourceTemplate ()
{
UartSerialBus (0x0001C200, DataBitsEight, StopBitsOne,
0xC0, LittleEndian, ParityTypeNone, FlowControlHardware,
0x0020, 0x0020, "\\_SB.PCI0.UA00",
0x00, ResourceConsumer, ,
)
})
Return (UBUF)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
}
}
# udevadm monitor --kernel --environment > ~/uart.uevents
# echo add > /sys/bus/uart/uevent
# echo add > /sys/bus/uart/devices/INTF001/uevent
# cat ~/uart.uevents
monitor will print the received events for:
KERNEL - the kernel uevent
KERNEL[252.443458] add /bus/uart (bus)
ACTION=add
DEVPATH=/bus/uart
SEQNUM=1142
SUBSYSTEM=bus
KERNEL[268.491709] add /devices/platform/INTF000:00/INTF001:00 (uart)
ACTION=add
DEVPATH=/devices/platform/INTF000:00/INTF001:00
DEVTYPE=uart_device
MODALIAS=uart:INTF001:00
SEQNUM=1144
SUBSYSTEM=uart
# cat /sys/bus/uart/devices/INTF001:00/modalias
uart:INTF001:00
# cat /sys/bus/uart/devices/INTF001:00/tty_dev
ttyS0
# cat /sys/bus/uart/devices/INTF001:00/tty_attrs
115200 8N0 HW
# cat /sys/bus/uart/devices/INTF001:00/modem_lines
LE:RTS,CTS,
# ls -l /sys/bus/uart/devices/
INTF001:00 -> ../../../devices/platform/INTF000:00/INTF001:00
# ls -l /sys/devices/platform/INTF000:00/INTF001:00/
firmware_node -> ../../../LNXSYSTM:00/device:00/INTF000:00/INTF001:00
subsystem -> ../../../../bus/uart
host_node -> ../tty/ttyS0
# ls -l /sys/devices/platform/INTF000:00/tty/ttyS0/
target_node -> ../../INTF001:00
# ls -l /sys/bus/acpi/INTF001:00/
physical_node -> ../../../../pnp0/00:00
physical_node1 -> ../../../../platform/INTF000:00/INTF001:00
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
drivers/acpi/scan.c | 1 +
drivers/tty/serial/8250/8250.c | 12 ++++
drivers/tty/serial/8250/8250_dummy.c | 129 ++++++++++++++++++++++++++++++++++
drivers/tty/serial/8250/Kconfig | 10 +++
drivers/tty/serial/8250/Makefile | 1 +
drivers/tty/serial/serial_bus.c | 17 +++++
include/linux/serial_bus.h | 5 ++
7 files changed, 175 insertions(+)
create mode 100644 drivers/tty/serial/8250/8250_dummy.c
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 4dd13e4..95c7528 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -36,6 +36,7 @@ static const char *dummy_hid = "device";
static const struct acpi_device_id acpi_platform_device_ids[] = {
{ "PNP0D40" },
+ { "INTF000" },
{ }
};
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index af78374..745e05d 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -35,6 +35,7 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
+#include <linux/serial_bus.h>
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -2986,6 +2987,8 @@ void serial8250_resume_port(int line)
uart_resume_port(&serial8250_reg, port);
}
+struct uart_device *uart_dummy;
+
/*
* Register a set of serial devices attached to a platform device. The
* list is terminated with a zero flags entry, which means we expect
@@ -2996,6 +2999,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
struct plat_serial8250_port *p = dev->dev.platform_data;
struct uart_8250_port uart;
int ret, i, irqflag = 0;
+ unsigned int dummy_line;
memset(&uart, 0, sizeof(uart));
@@ -3031,6 +3035,13 @@ static int __devinit serial8250_probe(struct platform_device *dev)
p->irq, ret);
}
}
+
+ dummy_line = serial8250_ports[nr_uarts-1].port.line;
+ pr_info("registering DUMMY at line %d.\n", dummy_line);
+ uart_dummy = uart_register_dummy(&dev->dev,
+ serial8250_reg.tty_driver,
+ dummy_line);
+
return 0;
}
@@ -3041,6 +3052,7 @@ static int __devexit serial8250_remove(struct platform_device *dev)
{
int i;
+ uart_unregister_device(uart_dummy);
for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
diff --git a/drivers/tty/serial/8250/8250_dummy.c b/drivers/tty/serial/8250/8250_dummy.c
new file mode 100644
index 0000000..c5ec064
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_dummy.c
@@ -0,0 +1,129 @@
+/*
+ * 8250_dummy.c: Dummy 8250 UART target device enumerator
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_bus.h>
+#include <linux/acpi.h>
+#include <linux/acpi_uart.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct dummy8250_data {
+ int last_lcr;
+ int line;
+};
+
+static void dummy8250_serial_out(struct uart_port *p, int offset, int value)
+{
+}
+
+static unsigned int dummy8250_serial_in(struct uart_port *p, int offset)
+{
+ return 0;
+}
+
+struct klist *dummy8250_mgr;
+int dummy8250_num;
+
+static int __devinit dummy8250_probe(struct platform_device *pdev)
+{
+ struct uart_8250_port uart = {};
+ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct dummy8250_data *data;
+#ifdef CONFIG_ACPI_UART
+ struct klist *mgr;
+#endif
+
+ dev_info(&pdev->dev, "1\n");
+ if (!regs) {
+ dev_err(&pdev->dev, "no registers defined\n");
+ return -EINVAL;
+ }
+
+ dev_info(&pdev->dev, "2\n");
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ uart.port.private_data = data;
+
+ spin_lock_init(&uart.port.lock);
+ uart.port.mapbase = regs->start;
+ uart.port.type = PORT_8250;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+ UPF_FIXED_PORT | UPF_FIXED_TYPE;
+ uart.port.dev = &pdev->dev;
+
+ uart.port.iotype = UPIO_MEM;
+ uart.port.serial_in = dummy8250_serial_in;
+ uart.port.serial_out = dummy8250_serial_out;
+ uart.port.uartclk = 40000000;
+
+ dev_info(&pdev->dev, "3\n");
+ data->line = serial8250_register_8250_port(&uart);
+ if (data->line < 0)
+ return data->line;
+
+#ifdef CONFIG_ACPI_UART
+ dev_info(&pdev->dev, "4\n");
+ mgr = acpi_uart_register_devices(dummy8250_mgr,
+ &pdev->dev,
+ serial8250_reg.tty_driver,
+ data->line);
+ if (mgr) {
+ dummy8250_mgr = mgr;
+ dummy8250_num++;
+ }
+#endif
+ dev_info(&pdev->dev, "5\n");
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int __devexit dummy8250_remove(struct platform_device *pdev)
+{
+ struct dummy8250_data *data = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_ACPI_UART
+ dummy8250_num--;
+ if (!dummy8250_num)
+ acpi_uart_unregister_devices(dummy8250_mgr);
+#endif
+ serial8250_unregister_port(data->line);
+
+ return 0;
+}
+
+static const struct acpi_device_id dummy8250_match[] = {
+ { .id = "INTF000" },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, dummy8250_match);
+
+static struct platform_driver dummy8250_platform_driver = {
+ .driver = {
+ .name = "dummy-uart",
+ .owner = THIS_MODULE,
+ .acpi_match_table = dummy8250_match,
+ },
+ .probe = dummy8250_probe,
+ .remove = __devexit_p(dummy8250_remove),
+};
+
+module_platform_driver(dummy8250_platform_driver);
+
+MODULE_AUTHOR("Lv Zheng");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Dummy 8250 serial port driver");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index f3d283f..3ba480a 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -270,6 +270,16 @@ config SERIAL_8250_DW
Selecting this option will enable handling of the extra features
present in the Synopsys DesignWare APB UART.
+config SERIAL_8250_DUMMY
+ tristate "Support for dummy ACPI 8250"
+ depends on SERIAL_8250 && ACPI
+ help
+ Selecting this option will enable a test UART target device DUMMY
+ under the ISA serial8250 and a test UART host adapter INTF000
+ as an platform device for the purpose of testing the ACPI UART
+ enumeration support.
+ If unsure, say "N" here.
+
config SERIAL_8250_EM
tristate "Support for Emma Mobile intergrated serial port"
depends on SERIAL_8250 && ARM && HAVE_CLK
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 108fe7f..fb82aa9 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o
+obj-$(CONFIG_SERIAL_8250_DUMMY) += 8250_dummy.o
diff --git a/drivers/tty/serial/serial_bus.c b/drivers/tty/serial/serial_bus.c
index 66c112d..033dd37 100644
--- a/drivers/tty/serial/serial_bus.c
+++ b/drivers/tty/serial/serial_bus.c
@@ -393,6 +393,23 @@ void uart_del_adapter(struct klist *adap)
}
EXPORT_SYMBOL_GPL(uart_del_adapter);
+static struct uart_board_info dummy_target = {
+ .type = "DUMMY",
+ .baud = 115200,
+ .cflag = CS8 | CSTOPB | CRTSCTS,
+ .iflag = (IXON | IXOFF),
+ .mctrl = TIOCM_LE | TIOCM_RTS,
+};
+
+struct uart_device *uart_register_dummy(struct device *dev,
+ struct tty_driver *drv,
+ unsigned int line)
+{
+ dummy_target.line = line;
+ return uart_register_device(NULL, dev, drv, &dummy_target);
+}
+EXPORT_SYMBOL_GPL(uart_register_dummy);
+
struct bus_type uart_bus_type = {
.name = "uart",
};
diff --git a/include/linux/serial_bus.h b/include/linux/serial_bus.h
index 1955d3e..7eb74b9 100644
--- a/include/linux/serial_bus.h
+++ b/include/linux/serial_bus.h
@@ -118,4 +118,9 @@ struct device *uart_tty_find(struct tty_driver *drv, unsigned int line,
struct device *dev);
void uart_tty_name(struct tty_driver *driver, unsigned int line, char *p);
+/* Test dummy device registration */
+struct uart_device *uart_register_dummy(struct device *dev,
+ struct tty_driver *drv,
+ unsigned int line);
+
#endif /* LINUX_SERIAL_BUS_H */
--
1.7.10
^ permalink raw reply related
* [RFC PATCH v3 3/4] UART / 8250: Add declearation of serial8250 driver.
From: Lv Zheng @ 2012-12-06 9:22 UTC (permalink / raw)
To: Len Brown, Rafael J Wysocki, Greg Kroah-Hartman, Alan Cox,
Mika Westerberg
Cc: linux-acpi, linux-serial, Lv Zheng
In-Reply-To: <cover.1354785372.git.lv.zheng@intel.com>
Export serial8250 uart driver for uart bus enumerator users.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
drivers/tty/serial/8250/8250.c | 5 ++---
include/linux/serial_8250.h | 2 ++
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 3ba4234..af78374 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -56,8 +56,6 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
-static struct uart_driver serial8250_reg;
-
static int serial_index(struct uart_port *port)
{
return (serial8250_reg.minor - 64) + port->line;
@@ -2902,7 +2900,7 @@ int serial8250_find_port(struct uart_port *p)
#define SERIAL8250_CONSOLE NULL
#endif
-static struct uart_driver serial8250_reg = {
+struct uart_driver serial8250_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
.dev_name = "ttyS",
@@ -2910,6 +2908,7 @@ static struct uart_driver serial8250_reg = {
.minor = 64,
.cons = SERIAL8250_CONSOLE,
};
+EXPORT_SYMBOL_GPL(serial8250_reg);
/*
* early_serial_setup - early registration for 8250 ports
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index c174c90..687af38 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -96,6 +96,8 @@ struct uart_8250_port {
void (*dl_write)(struct uart_8250_port *, int);
};
+extern struct uart_driver serial8250_reg;
+
int serial8250_register_8250_port(struct uart_8250_port *);
void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);
--
1.7.10
^ permalink raw reply related
* [RFC PATCH v3 2/4] ACPI / UART: Add ACPI enumeration support for UART bus.
From: Lv Zheng @ 2012-12-06 9:22 UTC (permalink / raw)
To: Len Brown, Rafael J Wysocki, Greg Kroah-Hartman, Alan Cox,
Mika Westerberg
Cc: linux-acpi, linux-serial, Lv Zheng
In-Reply-To: <cover.1354785372.git.lv.zheng@intel.com>
ACPI 5.0 specification introduces the methods of enumerating the target
devices connected on the serial buses.
This patch follows the specification, implementing such UART enumeration
machanism for the Linux.
In order to use this UART device enumeration mechanism, driver writers
are required to call the following APIs:
1. APIs called _after_ the creation of the uart ports:
adap = acpi_uart_register_devices(adap, parent, driver, line);
Where:
driver: the low level UART driver
parent: the physical device of the UART ports
adap: the management list of the target devices, can be set as NULL
line: the line number of the target device
2. APIs called _before_ the deletion of the uart ports:
acpi_uart_unregister_devices(adap);
Where:
adap: the management list of the UART target devices
NOTE: If the driver writer has already created the management list for
the UART target devices, the adap parameter can be set to the
already created non-NULL value.
NOTE: The ACPI 5.0 specification assumes one physical device per-port.
In this situation, the line parameter might be set to 0 when the
acpi_uart_register_devices() is called.
This patch set can also support the multi-port UART adapters,
where the line should be set as ACPI_UART_LINE_UNKNOWN.
The test result of ACPI bindings:
kobject sysfs links:
# ls -l /sys/bus/acpi/INTF001:00/
physical_node -> ../../../../pnp0/00:00
physical_node1 -> ../../../../platform/INTF000:00/INTF001:00
# ls -l /sys/devices/platform/INTF000:00/INTF001:00/
firmware_node -> ../../../LNXSYSTM:00/device:00/INTF000:00/INTF001:00
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
drivers/acpi/Kconfig | 7 ++
drivers/acpi/Makefile | 1 +
drivers/acpi/acpi_uart.c | 263 +++++++++++++++++++++++++++++++++++++++
drivers/tty/serial/serial_bus.c | 1 +
include/linux/acpi_uart.h | 40 ++++++
include/linux/serial_bus.h | 2 +
6 files changed, 314 insertions(+)
create mode 100644 drivers/acpi/acpi_uart.c
create mode 100644 include/linux/acpi_uart.h
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0300bf6..404df82 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -187,6 +187,12 @@ config ACPI_I2C
help
ACPI I2C enumeration support.
+config ACPI_UART
+ def_tristate SERIAL_BUS
+ depends on SERIAL_BUS
+ help
+ ACPI UART enumeration support.
+
config ACPI_PROCESSOR
tristate "Processor"
select THERMAL
@@ -200,6 +206,7 @@ config ACPI_PROCESSOR
To compile this driver as a module, choose M here:
the module will be called processor.
+
config ACPI_IPMI
tristate "IPMI"
depends on EXPERIMENTAL && IPMI_SI && IPMI_HANDLER
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 2a4502b..784f332 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o
+obj-$(CONFIG_ACPI_UART) += acpi_uart.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/acpi_uart.c b/drivers/acpi/acpi_uart.c
new file mode 100644
index 0000000..bfc584f
--- /dev/null
+++ b/drivers/acpi/acpi_uart.c
@@ -0,0 +1,263 @@
+/*
+ * acpi_uart.c - ACPI UART enumeration support
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/serial_bus.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/acpi_uart.h>
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+
+
+static int
+acpi_uart_add_resources(struct acpi_resource *ares, void *context)
+{
+ struct uart_board_info *info = context;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ struct acpi_resource_uart_serialbus *sb;
+
+ sb = &ares->data.uart_serial_bus;
+ if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+ return 1;
+
+ /* baud rate */
+ info->baud = sb->default_baud_rate;
+
+ /* data bits */
+ info->cflag &= ~CSIZE;
+ switch (sb->data_bits) {
+ case ACPI_UART_5_DATA_BITS:
+ info->cflag |= CS5;
+ break;
+ case ACPI_UART_6_DATA_BITS:
+ info->cflag |= CS6;
+ break;
+ case ACPI_UART_7_DATA_BITS:
+ info->cflag |= CS7;
+ break;
+ case ACPI_UART_8_DATA_BITS:
+ default:
+ info->cflag |= CS8;
+ break;
+ }
+
+ /* parity */
+ info->cflag &= ~(PARENB | PARODD);
+ if (sb->parity == ACPI_UART_PARITY_EVEN)
+ info->cflag |= PARENB;
+ else if (sb->parity == ACPI_UART_PARITY_ODD)
+ info->cflag |= (PARENB | PARODD);
+
+ /* stop bits */
+ if (sb->stop_bits == ACPI_UART_2_STOP_BITS)
+ info->cflag |= CSTOPB;
+ else
+ info->cflag &= ~CSTOPB;
+
+ /* HW control */
+ if (sb->flow_control & ACPI_UART_FLOW_CONTROL_HW)
+ info->cflag |= CRTSCTS;
+ else
+ info->cflag &= ~CRTSCTS;
+
+ /* SW control */
+ if (sb->flow_control & ACPI_UART_FLOW_CONTROL_XON_XOFF)
+ info->iflag |= (IXON | IXOFF);
+ else
+ info->iflag &= ~(IXON|IXOFF|IXANY);
+
+ /* endianess */
+ if (sb->endian == ACPI_UART_LITTLE_ENDIAN)
+ info->mctrl |= TIOCM_LE;
+ else
+ info->mctrl &= ~TIOCM_LE;
+
+ /* terminal lines */
+ if (sb->lines_enabled & ACPI_UART_DATA_TERMINAL_READY)
+ info->mctrl |= TIOCM_DTR;
+ else
+ info->mctrl &= ~TIOCM_DTR;
+ if (sb->lines_enabled & ACPI_UART_REQUEST_TO_SEND)
+ info->mctrl |= TIOCM_RTS;
+ else
+ info->mctrl &= ~TIOCM_RTS;
+
+ /* modem lines */
+ if (sb->lines_enabled & ACPI_UART_CLEAR_TO_SEND)
+ info->mctrl |= TIOCM_CTS;
+ else
+ info->mctrl &= ~TIOCM_CTS;
+ if (sb->lines_enabled & ACPI_UART_CARRIER_DETECT)
+ info->mctrl |= TIOCM_CAR;
+ else
+ info->mctrl &= ~TIOCM_CAR;
+ if (sb->lines_enabled & ACPI_UART_RING_INDICATOR)
+ info->mctrl |= TIOCM_RNG;
+ else
+ info->mctrl &= ~TIOCM_RNG;
+ if (sb->lines_enabled & ACPI_UART_DATA_SET_READY)
+ info->mctrl |= TIOCM_DSR;
+ else
+ info->mctrl &= ~TIOCM_DSR;
+ } else if (info->irq < 0) {
+ struct resource r;
+
+ if (acpi_dev_resource_interrupt(ares, 0, &r))
+ info->irq = r.start;
+ }
+
+ return 1;
+}
+
+struct acpi_uart_walk {
+ struct tty_driver *drv;
+ unsigned int line;
+ struct device *parent;
+};
+
+static acpi_status acpi_uart_add_device(acpi_handle handle, u32 level,
+ void *context, void **return_value)
+{
+ struct acpi_uart_walk *walk = context;
+ struct tty_driver *drv = walk->drv;
+ unsigned int line = walk->line;
+ struct device *parent = walk->parent;
+ struct acpi_device_info *info;
+ struct uart_board_info board_info;
+ struct acpi_device *adev;
+ struct list_head resource_list;
+ int ret;
+ acpi_status status;
+ struct klist *adap = *return_value;
+ struct uart_device *udev;
+
+ BUG_ON(!parent || !adap || !drv);
+
+ /*
+ * Current BIOS will create physical adapter DEVICE per port.
+ * This implementation assumes multi-port DEVICE will use _ADR
+ * as serial port line number though there is no such explicit
+ * proof for this assumption in the ACPI specification.
+ *
+ * NOTE: There is no real BIOS implementation using _ADR as line
+ * number.
+ */
+ if (line == ACPI_UART_LINE_UNKNOWN) {
+ status = acpi_get_object_info(handle, &info);
+ if (ACPI_FAILURE(status))
+ return AE_OK;
+ if (info->valid & ACPI_VALID_ADR)
+ line = info->address;
+ }
+
+ if (line == ACPI_UART_LINE_UNKNOWN)
+ return AE_OK;
+ if (acpi_bus_get_device(handle, &adev))
+ return AE_OK;
+ if (acpi_bus_get_status(adev) || !adev->status.present)
+ return AE_OK;
+
+ memset(&board_info, 0, sizeof(board_info));
+ board_info.acpi_node.handle = handle;
+ board_info.irq = -1;
+ board_info.line = line;
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ acpi_uart_add_resources, &board_info);
+ acpi_dev_free_resource_list(&resource_list);
+
+ if (ret < 0 || !board_info.baud)
+ return AE_OK;
+
+ strlcpy(board_info.type, dev_name(&adev->dev), sizeof(board_info.type));
+
+ udev = uart_register_device(adap, parent, drv, &board_info);
+ if (!udev) {
+ dev_err(&adev->dev, "failed to add #%d uart device from ACPI\n",
+ line);
+ return AE_OK;
+ }
+
+ return AE_OK;
+}
+
+/**
+ * acpi_uart_register_devices - register the uart slave devices behind the
+ * uart host adapter
+ * @adap: the logical uart host adapter
+ * @dev: the physical uart host adapter
+ * @drv: the tty host driver
+ * @line: the serial line number
+ *
+ * Enumerate all uart slave devices behind the adapter by walking the ACPI
+ * namespace. When a device is found, it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ * If the physical device is a multiple port device, line should be -1.
+ * If the physical device is a single port device, line should be the line
+ * number.
+ */
+struct klist *acpi_uart_register_devices(struct klist *adap,
+ struct device *parent,
+ struct tty_driver *drv,
+ unsigned int line)
+{
+ acpi_handle handle;
+ acpi_status status;
+ struct klist *klist = NULL;
+ struct acpi_uart_walk walk = {drv, line, parent};
+
+ BUG_ON(!drv || !parent);
+
+ handle = ACPI_HANDLE(parent);
+ if (!handle)
+ return NULL;
+
+ if (!adap) {
+ klist = kzalloc(sizeof(struct klist), GFP_KERNEL);
+ if (!klist)
+ return NULL;
+ (void)uart_add_adapter(klist);
+ adap = klist;
+ }
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ acpi_uart_add_device, NULL, &walk,
+ (void **)&adap);
+ if (ACPI_FAILURE(status)) {
+ dev_warn(parent, "failed to enumerate UART slaves\n");
+ goto fail;
+ }
+
+ return adap;
+
+fail:
+ uart_del_adapter(klist);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(acpi_uart_register_devices);
+
+/**
+ * acpi_uart_register_devices - unregister the uart slave devices behind the
+ * uart host adapter
+ * @adap: the logical uart host adapter
+ *
+ * Reverse effect of acpi_uart_register_devices().
+ */
+void acpi_uart_unregister_devices(struct klist *adap)
+{
+ uart_del_adapter(adap);
+ kfree(adap);
+}
+EXPORT_SYMBOL_GPL(acpi_uart_unregister_devices);
diff --git a/drivers/tty/serial/serial_bus.c b/drivers/tty/serial/serial_bus.c
index ddb5341..66c112d 100644
--- a/drivers/tty/serial/serial_bus.c
+++ b/drivers/tty/serial/serial_bus.c
@@ -281,6 +281,7 @@ struct uart_device *uart_register_device(struct klist *adap,
udev->dev.parent = dev;
udev->dev.bus = &uart_bus_type;
udev->dev.type = &uart_device_type;
+ ACPI_HANDLE_SET(&udev->dev, info->acpi_node.handle);
tty = uart_tty_find(drv, info->line, dev);
if (!tty) {
diff --git a/include/linux/acpi_uart.h b/include/linux/acpi_uart.h
new file mode 100644
index 0000000..a928425
--- /dev/null
+++ b/include/linux/acpi_uart.h
@@ -0,0 +1,40 @@
+/*
+ * acpi_uart.h - ACPI UART enumeration support
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef _LINUX_ACPI_UART_H
+#define _LINUX_ACPI_UART_H
+
+struct uart_driver;
+
+#define ACPI_UART_LINE_UNKNOWN ((unsigned int)-1)
+
+#if IS_ENABLED(CONFIG_ACPI_UART)
+struct klist *acpi_uart_register_devices(struct klist *adap,
+ struct device *parent,
+ struct tty_driver *drv,
+ unsigned int line);
+void acpi_uart_unregister_devices(struct klist *adap);
+#else
+static inline struct klist *acpi_uart_register_devices(struct klist *adap,
+ struct device *parent,
+ struct tty_driver *drv,
+ unsigned int line)
+{
+ return NULL;
+}
+
+static inline void acpi_uart_unregister_devices(struct klist *adap)
+{
+}
+#endif
+
+#endif /* _LINUX_ACPI_UART_H */
diff --git a/include/linux/serial_bus.h b/include/linux/serial_bus.h
index d8b56ae..1955d3e 100644
--- a/include/linux/serial_bus.h
+++ b/include/linux/serial_bus.h
@@ -34,6 +34,7 @@ struct uart_device;
* @irq: stored in uart_device.irq
* @platform_data: stored in uart_device.dev.platform_data
* @archdata: copied into uart_device.dev.archdata
+ * @acpi_node: ACPI device node
*
* uart_board_info is used to build tables of information listing UART
* devices that are present. This information is used to grow the driver
@@ -50,6 +51,7 @@ struct uart_board_info {
int irq;
void *platform_data;
struct dev_archdata *archdata;
+ struct acpi_dev_node acpi_node;
};
extern struct bus_type uart_bus_type;
--
1.7.10
^ permalink raw reply related
* [RFC PATCH v3 1/4] UART: Add UART subsystem as a bus.
From: Lv Zheng @ 2012-12-06 9:21 UTC (permalink / raw)
To: Len Brown, Rafael J Wysocki, Greg Kroah-Hartman, Alan Cox,
Mika Westerberg
Cc: linux-acpi, linux-serial, Lv Zheng
In-Reply-To: <cover.1354785372.git.lv.zheng@intel.com>
Tranditional UARTs are used as communication pipes between the hosts
while the modern computing systems equipped with HSU (High Speed UARTs)
would connect on-board target devices using the UART ports. The role of
the UART controllers is changed from the communication facility to the
platform bus.
In the recent ACPI 5.0 specification updates, firmwares are provided the
possibilities to enumerate the UART target devices known to the platform
vendors.
Thus there are the needs for enumerating the UART target devices:
1. hotplug uevent
2. serial configuration
Currently, only serial cards on the specific bus (ex. PCMCIA) can be
enumerated and userspace can obtain the hotplug event of the UART target
devices. Linux kernel is lack of an overall enumeration mechanism for
UART target devices.
In order to send uevent, a device need to be a class device or a bus
device. This patch introduces a bus_type subsystem to manage the new
UART target device type for the purpose of being ready for the possible
future extensions.
When the UART target devices are created, userspace uevent rules can
pass the creation details to the userspace driver managers
(ex. hciattach). Here is an example of the uevents and exported
attributes of these new UART target devices:
Test DSDT (dummy UART host adapter INTF000 and target device INTF001):
Device (UA00)
{
Name (_HID, "INTF000") // _HID: Hardware ID
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0x00000000, // Address Base
0x00001000) // Address Length
})
Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Return (RBUF)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Device (BTH0)
{
Name (_HID, "INTF001") // _HID: Hardware ID
Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Name (UBUF, ResourceTemplate ()
{
UartSerialBus (0x0001C200, DataBitsEight, StopBitsOne,
0xC0, LittleEndian, ParityTypeNone, FlowControlHardware,
0x0020, 0x0020, "\\_SB.PCI0.UA00",
0x00, ResourceConsumer, ,
)
})
Return (UBUF)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
}
}
The test result of hotplug event monitoring:
uevent and environments:
KERNEL[252.443458] add /bus/uart (bus)
ACTION=add
DEVPATH=/bus/uart
SEQNUM=1142
SUBSYSTEM=bus
KERNEL[268.491709] add /devices/platform/INTF000:00/INTF001:00 (uart)
ACTION=add
DEVPATH=/devices/platform/INTF000:00/INTF001:00
DEVTYPE=uart_device
MODALIAS=uart:INTF001:00
SEQNUM=1144
SUBSYSTEM=uart
The test result of the UART target device enumeration:
kobject attribute files:
# cat /sys/bus/uart/devices/INTF001:00/modalias
uart:INTF001:00
# cat /sys/bus/uart/devices/INTF001:00/tty_dev
ttyS0
# cat /sys/bus/uart/devices/INTF001:00/tty_attrs
115200 8N0 HW
# cat /sys/bus/uart/devices/INTF001:00/modem_lines
LE:RTS,CTS,
kobject sysfs links:
# ls -l /sys/bus/uart/devices/
INTF001:00 -> ../../../devices/platform/INTF000:00/INTF001:00
# ls -l /sys/devices/platform/INTF000:00/INTF001:00/
subsystem -> ../../../../bus/uart
host_node -> ../tty/ttyS0
# ls -l /sys/devices/platform/INTF000:00/tty/ttyS0/
target_node -> ../../INTF001:00
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
drivers/tty/serial/Kconfig | 8 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/serial_bus.c | 417 +++++++++++++++++++++++++++++++++++++++
include/linux/mod_devicetable.h | 5 +
include/linux/serial_bus.h | 119 +++++++++++
5 files changed, 550 insertions(+)
create mode 100644 drivers/tty/serial/serial_bus.c
create mode 100644 include/linux/serial_bus.h
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2a53be5..e16b03a 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -749,6 +749,14 @@ config SERIAL_HS_LPC32XX_CONSOLE
ports on the LPC32XX as the console, you can do so by answering
Y to this option.
+config SERIAL_BUS
+ bool "Enable Serial bus enumerator support"
+ help
+ If your platform has enumeration support for the serial target
+ devices, you can enable this option by say Y here. Such
+ enumeration mechanisms are always provided by the firmwares.
+ If unsure, say N.
+
config SERIAL_CORE
tristate
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 4f694da..9a05bbc 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -3,6 +3,7 @@
#
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
+obj-$(CONFIG_SERIAL_BUS) += serial_bus.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
# These Sparc drivers have to appear before others such as 8250
diff --git a/drivers/tty/serial/serial_bus.c b/drivers/tty/serial/serial_bus.c
new file mode 100644
index 0000000..ddb5341
--- /dev/null
+++ b/drivers/tty/serial/serial_bus.c
@@ -0,0 +1,417 @@
+/*
+ * serial_bus.c - UART bus implementation
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * Tranditional UARTs are used as communication pipes between the hosts
+ * while the modern computing systems equipped with HSU (High Speed UARTs)
+ * would connect on-board target devices using the UART ports. The role of
+ * the UART controllers are changed from the communication facility to the
+ * platform bus.
+ *
+ * UART target devices are created in the kernel as struct uart_device.
+ * It is defined for the following purposes:
+ * 1. Sending hotplug notifications to the userspace
+ * 2. Exporting serial configuration parameters to the userspace
+ * 3. Allowing target device based PM to be added easily
+ *
+ */
+
+#include <linux/serial.h>
+#include <linux/serial_bus.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+
+struct uart_match {
+ dev_t devt;
+};
+
+static int do_uart_tty_find(struct device *dev, void *data)
+{
+ struct uart_match *match = data;
+ return dev->devt == match->devt;
+}
+
+/**
+ * uart_tty_find - find the tty device using the line number
+ * @drv: the tty host driver
+ * @line: the line number of the tty device
+ * @dev: the physical uart host adapter
+ *
+ * Return a matching tty device on the host adapter.
+ */
+struct device *uart_tty_find(struct tty_driver *drv, unsigned int line,
+ struct device *dev)
+{
+ struct uart_match match;
+
+ match.devt = MKDEV(drv->major, drv->minor_start + line);
+
+ return device_find_child(dev, &match, do_uart_tty_find);
+}
+EXPORT_SYMBOL_GPL(uart_tty_find);
+
+/**
+ * uart_tty_name - get the name of the tty device according to the line
+ * number
+ * @drv: the tty host driver
+ * @line: the line number of the tty device
+ * @p: pointer to the buffer containing the returned name
+ *
+ * Return the name of the tty device.
+ */
+void uart_tty_name(struct tty_driver *drv, unsigned int line, char *p)
+{
+ BUG_ON(!drv || !p);
+
+ if (drv->flags & TTY_DRIVER_UNNUMBERED_NODE)
+ strcpy(p, drv->name);
+ else
+ sprintf(p, "%s%d", drv->name, line + drv->name_base);
+}
+EXPORT_SYMBOL_GPL(uart_tty_name);
+
+static ssize_t uart_dev_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct uart_device *udev = to_uart_device(dev);
+ return sprintf(buf, "%s\n", udev->name);
+}
+
+static ssize_t uart_dev_show_modalias(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct uart_device *udev = to_uart_device(dev);
+ return sprintf(buf, "%s%s\n", UART_MODULE_PREFIX, udev->name);
+}
+
+static ssize_t uart_dev_show_tty_dev(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct uart_device *udev = to_uart_device(dev);
+ return sprintf(buf, "%s\n", udev->tty_name);
+}
+
+static ssize_t uart_dev_show_tty_attrs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct uart_device *udev = to_uart_device(dev);
+ int len = 0;
+
+ /* baud rate */
+ len += sprintf(buf+len, "%d ", udev->baud);
+
+ /* data bits */
+ switch (udev->cflag & CSIZE) {
+ case CS5:
+ len += sprintf(buf+len, "5");
+ break;
+ case CS6:
+ len += sprintf(buf+len, "6");
+ break;
+ case CS7:
+ len += sprintf(buf+len, "7");
+ break;
+ case CS8:
+ default:
+ len += sprintf(buf+len, "8");
+ break;
+ }
+
+ /* parity */
+ if (udev->cflag & PARODD)
+ len += sprintf(buf+len, "O");
+ else if (udev->cflag & PARENB)
+ len += sprintf(buf+len, "E");
+ else
+ len += sprintf(buf+len, "N");
+
+ /* stop bits */
+ len += sprintf(buf+len, "%d", udev->cflag & CSTOPB ? 1 : 0);
+
+ /* HW/SW control */
+ if (udev->cflag & CRTSCTS)
+ len += sprintf(buf+len, " HW");
+ if ((udev->iflag & (IXON|IXOFF|IXANY)) != 0)
+ len += sprintf(buf+len, " SW");
+
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+
+static ssize_t uart_dev_show_modem_lines(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct uart_device *udev = to_uart_device(dev);
+ int len = 0;
+
+ /* endian */
+ if (udev->mctrl & TIOCM_LE)
+ len += sprintf(buf+len, "LE:");
+ else
+ len += sprintf(buf+len, "BE:");
+
+ /* terminal lines */
+ if (udev->mctrl & TIOCM_DTR)
+ len += sprintf(buf+len, "DTR,");
+ if (udev->mctrl & TIOCM_RTS)
+ len += sprintf(buf+len, "RTS,");
+
+ /* modem lines */
+ if (udev->mctrl & TIOCM_CTS)
+ len += sprintf(buf+len, "CTS,");
+ if (udev->mctrl & TIOCM_CAR)
+ len += sprintf(buf+len, "CAR,");
+ if (udev->mctrl & TIOCM_RNG)
+ len += sprintf(buf+len, "RNG,");
+ if (udev->mctrl & TIOCM_DSR)
+ len += sprintf(buf+len, "DSR,");
+
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+
+static DEVICE_ATTR(name, S_IRUGO, uart_dev_show_name, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, uart_dev_show_modalias, NULL);
+static DEVICE_ATTR(tty_dev, S_IRUGO, uart_dev_show_tty_dev, NULL);
+static DEVICE_ATTR(tty_attrs, S_IRUGO, uart_dev_show_tty_attrs, NULL);
+static DEVICE_ATTR(modem_lines, S_IRUGO, uart_dev_show_modem_lines, NULL);
+
+static struct attribute *uart_dev_attrs[] = {
+ &dev_attr_name.attr,
+ /* coldplug: modprobe $(cat .../modalias) */
+ &dev_attr_modalias.attr,
+ &dev_attr_tty_dev.attr,
+ &dev_attr_tty_attrs.attr,
+ &dev_attr_modem_lines.attr,
+ NULL,
+};
+
+static struct attribute_group uart_dev_attr_group = {
+ .attrs = uart_dev_attrs,
+};
+
+static const struct attribute_group *uart_dev_attr_groups[] = {
+ &uart_dev_attr_group,
+ NULL,
+};
+
+#ifdef CONFIG_HOTPLUG
+static int uart_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct uart_device *udev = to_uart_device(dev);
+
+ if (add_uevent_var(env, "MODALIAS=%s%s",
+ UART_MODULE_PREFIX, udev->name))
+ return -ENOMEM;
+
+ dev_dbg(dev, "uevent\n");
+ return 0;
+}
+#else
+#define uart_device_uevent NULL
+#endif
+
+static void uart_device_release(struct device *dev)
+{
+ struct uart_device *udev = to_uart_device(dev);
+
+ put_device(udev->tty);
+ kfree(udev);
+}
+
+struct device_type uart_device_type = {
+ .name = "uart_device",
+ .groups = uart_dev_attr_groups,
+ .uevent = uart_device_uevent,
+ .release = uart_device_release,
+};
+EXPORT_SYMBOL_GPL(uart_device_type);
+
+/**
+ * uart_register_device - register a physical uart target device
+ * @adap: the logical uart host adapter
+ * @dev: the physical uart host adapter
+ * @drv: the tty host driver
+ * @info: the uart target device description
+ *
+ * Initialize and add a physical uart target device.
+ *
+ * This returns the new uart target device, which may be saved for later use
+ * with uart_unregister_device; or NULL to indicate an error.
+ */
+struct uart_device *uart_register_device(struct klist *adap,
+ struct device *dev,
+ struct tty_driver *drv,
+ struct uart_board_info const *info)
+{
+ struct uart_device *udev;
+ struct device *tty;
+ int status;
+
+ BUG_ON((!adap && !dev) || !drv);
+
+ udev = kzalloc(sizeof(struct uart_device), GFP_KERNEL);
+ if (!udev)
+ return NULL;
+
+ udev->dev.platform_data = info->platform_data;
+ if (info->archdata)
+ udev->dev.archdata = *info->archdata;
+
+ udev->baud = info->baud;
+ udev->cflag = info->cflag;
+ udev->iflag = info->iflag;
+ udev->mctrl = info->mctrl;
+ udev->irq = info->irq;
+
+ strlcpy(udev->name, info->type, sizeof(udev->name));
+
+ udev->dev.parent = dev;
+ udev->dev.bus = &uart_bus_type;
+ udev->dev.type = &uart_device_type;
+
+ tty = uart_tty_find(drv, info->line, dev);
+ if (!tty) {
+ dev_err(dev, "Cannot find associated tty device at line %d.\n",
+ info->line);
+ goto fail;
+ }
+ udev->tty = get_device(tty);
+ uart_tty_name(drv, info->line, udev->tty_name);
+
+ dev_set_name(&udev->dev, "%s", udev->name);
+ status = device_register(&udev->dev);
+ if (status) {
+ dev_err(dev,
+ "Failed to register uart target device at line %d.\n",
+ info->line);
+ goto fail2;
+ }
+ dev_info(&udev->dev, "Registered at line %d.\n", info->line);
+
+ status = sysfs_create_link(&tty->kobj, &udev->dev.kobj, "target_node");
+ status = sysfs_create_link(&udev->dev.kobj, &tty->kobj, "host_node");
+
+ if (adap) {
+ udev->adap = adap;
+ klist_add_tail(&udev->klist_parent, adap);
+ }
+
+ return udev;
+
+fail2:
+ put_device(tty);
+fail:
+ kfree(udev);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(uart_register_device);
+
+/**
+ * uart_unregister_device - unregister a physical uart target device
+ * @udev: the physical uart target device
+ *
+ * Reverse effect of uart_register_device().
+ */
+void uart_unregister_device(struct uart_device *udev)
+{
+ if (!udev)
+ return;
+ dev_info(&udev->dev, "Unregistering...\n");
+
+ if (udev->adap)
+ klist_del(&udev->klist_parent);
+ sysfs_remove_link(&udev->dev.kobj, "host_node");
+ if (udev->tty)
+ sysfs_remove_link(&udev->tty->kobj, "target_node");
+ device_unregister(&udev->dev);
+}
+EXPORT_SYMBOL_GPL(uart_unregister_device);
+
+static void klist_uart_get(struct klist_node *n)
+{
+ struct uart_device *udev = uart_device_from_parent(n);
+ get_device(&udev->dev);
+}
+
+static void klist_uart_put(struct klist_node *n)
+{
+ struct uart_device *udev = uart_device_from_parent(n);
+ put_device(&udev->dev);
+}
+
+static struct uart_device *uart_next_device(struct klist_iter *i)
+{
+ struct klist_node *n = klist_next(i);
+ return n ? uart_device_from_parent(n) : NULL;
+}
+
+/**
+ * uart_add_adapter - register a logical uart host adapter
+ * @adap: the logical uart host adapter
+ *
+ * Initialize a logical uart host adapter.
+ */
+int uart_add_adapter(struct klist *adap)
+{
+ klist_init(adap, klist_uart_get, klist_uart_put);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(uart_add_adapter);
+
+/**
+ * uart_del_adapter - unregister a logical uart host adapter
+ * @adap: the logical uart host adapter
+ *
+ * Reverse effect of uart_add_adapter().
+ */
+void uart_del_adapter(struct klist *adap)
+{
+ struct klist_iter i;
+ struct uart_device *udev;
+
+ if (!adap)
+ return;
+
+ klist_iter_init(adap, &i);
+ while ((udev = uart_next_device(&i)))
+ uart_unregister_device(udev);
+ klist_iter_exit(&i);
+}
+EXPORT_SYMBOL_GPL(uart_del_adapter);
+
+struct bus_type uart_bus_type = {
+ .name = "uart",
+};
+EXPORT_SYMBOL_GPL(uart_bus_type);
+
+static int __init uart_bus_init(void)
+{
+ int retval;
+
+ retval = bus_register(&uart_bus_type);
+ if (retval)
+ return retval;
+
+ return 0;
+}
+
+static void __exit uart_bus_exit(void)
+{
+ bus_unregister(&uart_bus_type);
+}
+
+subsys_initcall(uart_bus_init);
+module_exit(uart_bus_exit);
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index fed3def..28df140 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -455,6 +455,11 @@ struct spi_device_id {
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
+/* uart */
+
+#define UART_NAME_SIZE 32
+#define UART_MODULE_PREFIX "uart:"
+
/* dmi */
enum dmi_field {
DMI_NONE,
diff --git a/include/linux/serial_bus.h b/include/linux/serial_bus.h
new file mode 100644
index 0000000..d8b56ae
--- /dev/null
+++ b/include/linux/serial_bus.h
@@ -0,0 +1,119 @@
+/*
+ * serial_bus.h - UART bus implementation
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef LINUX_SERIAL_BUS_H
+#define LINUX_SERIAL_BUS_H
+
+#include <linux/compiler.h>
+#include <linux/tty.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+struct uart_device;
+
+/**
+ * struct uart_board_info - template for device creation
+ * @type: chip type, to initialize uart_devide.name
+ * @line: line number, to find associated tty device
+ * @cflag: termio cflag, preferred termio cflag to be used to communicate
+ * with this target device
+ * @iflag: termio iflag, preferred termio iflag to be used to communicate
+ * with this target device
+ * @mctrl: termio mctrl, preferred termio mctrl to be used to communicate
+ * with this target device
+ * @baud: termio baud, preferred termio baud rate to be used to communicate
+ * with this target device
+ * @irq: stored in uart_device.irq
+ * @platform_data: stored in uart_device.dev.platform_data
+ * @archdata: copied into uart_device.dev.archdata
+ *
+ * uart_board_info is used to build tables of information listing UART
+ * devices that are present. This information is used to grow the driver
+ * model tree. For add-on boards, uart_register_device() does this
+ * dynamically with the host side physical device already known.
+ */
+struct uart_board_info {
+ char type[UART_NAME_SIZE];
+ unsigned int line; /* port index */
+ unsigned int cflag; /* termio cflag */
+ unsigned int iflag; /* termio iflag */
+ unsigned int mctrl; /* modem ctrl settings */
+ unsigned int baud;
+ int irq;
+ void *platform_data;
+ struct dev_archdata *archdata;
+};
+
+extern struct bus_type uart_bus_type;
+
+int uart_add_adapter(struct klist *adap);
+void uart_del_adapter(struct klist *adap);
+
+/**
+ * struct uart_device - represent a UART target device
+ * @name: Indicates the type of the device, usually a chip name that's
+ * generic enough to hide second-sourcing and compatible revisions
+ * @tty_name: associated tty device name
+ * @cflag: preferred termio cflag used to communicate with this target
+ * device
+ * @iflag: preferred termio iflag used to communicate with this target
+ * device
+ * @mctrl: preferred termio mctrl used to communicate with this target
+ * device
+ * @baud: preferred termio baud rate used to communicate with this target
+ * device
+ * @irq: indicates the IRQ generated by this target device (if any)
+ * @dev: driver model device node for the target device
+ * @tty: associated tty device
+ * @klist_parent: link to the logical adapter device that manages this
+ * target device
+ * @adap: logical adapter device that manages this target device
+ *
+ * A uart_device identifies a single device (i.e. chip) connected to a
+ * uart port.
+ */
+struct uart_device {
+ char name[UART_NAME_SIZE];
+ char tty_name[64];
+ unsigned int cflag; /* termio cflag */
+ unsigned int iflag; /* termio iflag */
+ unsigned int mctrl; /* modem ctrl settings */
+ unsigned int baud;
+ struct device dev;
+ int irq; /* irq issued by device */
+ struct device *tty;
+ struct klist_node klist_parent;
+ struct klist *adap; /* set for multi-port adapter */
+};
+
+extern struct device_type uart_device_type;
+
+#define is_uart_device(d) ((d) && (d)->type == &uart_device_type)
+#define to_uart_device(d) container_of(d, struct uart_device, dev)
+#define uart_device_from_parent(n) \
+ container_of(n, struct uart_device, klist_parent)
+
+static inline struct uart_device *uart_verify_device(struct device *dev)
+{
+ return is_uart_device(dev) ? to_uart_device(dev) : NULL;
+}
+
+struct uart_device *uart_register_device(struct klist *adap,
+ struct device *dev,
+ struct tty_driver *drv,
+ struct uart_board_info const *info);
+void uart_unregister_device(struct uart_device *udev);
+
+struct device *uart_tty_find(struct tty_driver *drv, unsigned int line,
+ struct device *dev);
+void uart_tty_name(struct tty_driver *driver, unsigned int line, char *p);
+
+#endif /* LINUX_SERIAL_BUS_H */
--
1.7.10
^ permalink raw reply related
* [RFC PATCH v3 0/4] ACPI/UART: Add ACPI 5.0 enueration support for UART.
From: Lv Zheng @ 2012-12-06 9:21 UTC (permalink / raw)
To: Len Brown, Rafael J Wysocki, Greg Kroah-Hartman, Alan Cox,
Mika Westerberg
Cc: linux-acpi, linux-serial, Lv Zheng
In-Reply-To: <cover.1354505471.git.lv.zheng@intel.com>
ACPI 5.0 specification introduces enumeration support for SPB buses. This
patch set adds the UART serial bus enumeration support to Linux using such
mechanism.
NOTE: The [PATCH 4/4] is only for the demonstration purpose and should not
be merged into any of the published Linux source tree.
History:
v1:
1. Add uart bus type subsystem (uart_bus).
2. Add physical uart target device and description
(uart_device/uart_board_info).
3. Add logical uart host adapter (klist).
4. Add uart target device attributes (tty_dev/tty_attrs/modem_lines).
5. Create tty_device<->uart_device links (host_node/target_node).
v2.
1. Change uart layer related stuff to tty layer.
2. Modify the order of the function parameters.
v3:
1. Add comments for the uart_board_info and the uart_device.
2. Add platform_data/archdata support.
3. Add ACPI binding and test the binding.
4. Add SERIAL_BUS kconfig item.
RFCs:
1. Do we need to rename uart_bus to tty_bus and rename uart_device to
tty_target?
2. Do we need a kernel driver for the uart_device?
3. Do we need to split uart_board_info.type into uart_board_info.id and
uart_board_info.type? How can ACPI fill the uart_board_info.type?
4. Do we need to set line discipline for the uart_board_info?
Lv Zheng (4):
UART: Add UART subsystem as a bus.
ACPI / UART: Add ACPI enumeration support for UART bus.
UART / 8250: Add declearation of serial8250 driver.
UART: Add dummy devices to test the enumeration.
drivers/acpi/Kconfig | 7 +
drivers/acpi/Makefile | 1 +
drivers/acpi/acpi_uart.c | 263 ++++++++++++++++++++
drivers/acpi/scan.c | 1 +
drivers/tty/serial/8250/8250.c | 17 +-
drivers/tty/serial/8250/8250_dummy.c | 129 ++++++++++
drivers/tty/serial/8250/Kconfig | 10 +
drivers/tty/serial/8250/Makefile | 1 +
drivers/tty/serial/Kconfig | 8 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/serial_bus.c | 435 ++++++++++++++++++++++++++++++++++
include/linux/acpi_uart.h | 40 ++++
include/linux/mod_devicetable.h | 5 +
include/linux/serial_8250.h | 2 +
include/linux/serial_bus.h | 126 ++++++++++
15 files changed, 1043 insertions(+), 3 deletions(-)
create mode 100644 drivers/acpi/acpi_uart.c
create mode 100644 drivers/tty/serial/8250/8250_dummy.c
create mode 100644 drivers/tty/serial/serial_bus.c
create mode 100644 include/linux/acpi_uart.h
create mode 100644 include/linux/serial_bus.h
--
1.7.10
^ permalink raw reply
* [PATCH] serial: omap: add the functionality of a 9-bit UART with userspaces CMSPAR
From: Enric Balletbo i Serra @ 2012-12-06 8:45 UTC (permalink / raw)
To: Alan Cox, Greg Kroah-Hartman, linux-serial, linux-omap
Cc: Enric Balletbo i Serra
From: Enric Balletbo i Serra <eballetbo@iseebcn.com>
Some systems require the additional communication functionality of a
9-bit UART. For that we could use the "stick" (mark/space) parity
bit supported on omap serial device. When is set, if PARODD is set the
parity bit is always 1; if PARODD is not set, then the parity bit is
always 0.
Signed-off-by: Enric Balletbo i Serra <eballetbo@iseebcn.com>
---
drivers/tty/serial/omap-serial.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6d3d26a..197fb71 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -756,6 +756,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
cval |= UART_LCR_PARITY;
if (!(termios->c_cflag & PARODD))
cval |= UART_LCR_EPAR;
+ if (termios->c_cflag & CMSPAR)
+ cval |= UART_LCR_SPAR;
/*
* Ask the core to calculate the divisor for us.
--
1.7.10.4
^ permalink raw reply related
* Re: [RFC PATCH 1/3] UART: Add UART subsystem as a bus.
From: Mika Westerberg @ 2012-12-06 7:52 UTC (permalink / raw)
To: Zheng, Lv
Cc: Alan Cox, Alan Cox, Brown, Len, Wysocki, Rafael J,
Greg Kroah-Hartman, linux-acpi@vger.kernel.org,
linux-serial@vger.kernel.org
In-Reply-To: <1AE640813FDE7649BE1B193DEA596E88BD70E6@SHSMSX101.ccr.corp.intel.com>
On Thu, Dec 06, 2012 at 07:36:35AM +0000, Zheng, Lv wrote:
> > > > The property should not be in any ACPI specific form or space - just
> > > > attach it directly to the tty from ACPI, DT, driver internal
> > > > knowledge, PCI id, whatever
> > >
> > > The only property that comes into mind is _HID/_CID (referring to the
> > > ACPI
> > > ID) that can be used by userspace to find out type of the device
> > > behind the UART port. I don't know what name would be generic enough
> > > for the property, though.
> >
> > We just need a set of type names for the sysfs node I think "bluetooth", "ups",
> > "loconet", "serial", "modem", "cir" etc...
>
> Hi, Mika
>
> How is this handled in the i2c?
We match the I2C device to the driver using _HID/_CID in the kernel. There
is no userpace involved (except maybe loading the correct driver module).
> I think for OF, type can be filled as "bluetooth", "ups" and etc.
> But for ACPI, the type field of the i2c_board_info is filled as hid in your patches.
> Is this right?
Yes.
> Maybe I just need to add struct acpi_dev_node to the uart_board_info and
> let OF guys add of_node to it. What's your opinion?
Well, in order to use any ACPI functions and PM you need to have
ACPI_HANDLE(dev) != NULL. If the best place to pass that handle is
uart_board_info (in analogy to i2c_board_info), then yes you should add it
there.
^ permalink raw reply
* RE: [RFC PATCH 1/3] UART: Add UART subsystem as a bus.
From: Zheng, Lv @ 2012-12-06 7:36 UTC (permalink / raw)
To: Alan Cox, Mika Westerberg
Cc: Alan Cox, Brown, Len, Wysocki, Rafael J, Greg Kroah-Hartman,
linux-acpi@vger.kernel.org, linux-serial@vger.kernel.org
In-Reply-To: <20121205094343.09d653c5@pyramind.ukuu.org.uk>
> > > The property should not be in any ACPI specific form or space - just
> > > attach it directly to the tty from ACPI, DT, driver internal
> > > knowledge, PCI id, whatever
> >
> > The only property that comes into mind is _HID/_CID (referring to the
> > ACPI
> > ID) that can be used by userspace to find out type of the device
> > behind the UART port. I don't know what name would be generic enough
> > for the property, though.
>
> We just need a set of type names for the sysfs node I think "bluetooth", "ups",
> "loconet", "serial", "modem", "cir" etc...
Hi, Mika
How is this handled in the i2c?
I think for OF, type can be filled as "bluetooth", "ups" and etc.
But for ACPI, the type field of the i2c_board_info is filled as hid in your patches.
Is this right?
Maybe I just need to add struct acpi_dev_node to the uart_board_info and let OF guys add of_node to it.
What's your opinion?
Best regards
-Lv
^ permalink raw reply
* RE: [RFC PATCH 1/3] UART: Add UART subsystem as a bus.
From: Zheng, Lv @ 2012-12-06 1:55 UTC (permalink / raw)
To: Zheng, Lv, Alan Cox, Mika Westerberg
Cc: Alan Cox, Brown, Len, Wysocki, Rafael J, Greg Kroah-Hartman,
linux-acpi@vger.kernel.org, linux-serial@vger.kernel.org,
Heikki Krogerus, Mathias Nyman, Huang, Ying
In-Reply-To: <1AE640813FDE7649BE1B193DEA596E88BD6C94@SHSMSX101.ccr.corp.intel.com>
> > > > The property should not be in any ACPI specific form or space -
> > > > just attach it directly to the tty from ACPI, DT, driver internal
> > > > knowledge, PCI id, whatever
> > >
> > > The only property that comes into mind is _HID/_CID (referring to
> > > the ACPI
> > > ID) that can be used by userspace to find out type of the device
> > > behind the UART port. I don't know what name would be generic enough
> > > for the property, though.
> >
> > We just need a set of type names for the sysfs node I think
> > "bluetooth", "ups", "loconet", "serial", "modem", "cir" etc...
>
> Is it a good idea to introduce uart_device driver in the kernel to fill a new 'ldisc'
> member in the uart_device or to load ldisc by default for the corresponding
> tty_port?
In the ACPI spec, there is no such attribute for the UART devices, OF might easily introduce this.
It's hard to add type name or ldisc name directly to the uart_board_info.
We can either add driver support for the uart_device to fill this as I mentioned in the first reply or to add a HID -> type name (or ldisc name) matching table in the acpi_uart.c to extract this information for the ACPI enumerated uart_board_info.
Best regards/Lv Zheng
^ permalink raw reply
* RE: [RFC PATCH 1/3] UART: Add UART subsystem as a bus.
From: Zheng, Lv @ 2012-12-06 1:26 UTC (permalink / raw)
To: Alan Cox, Mika Westerberg
Cc: Alan Cox, Brown, Len, Wysocki, Rafael J, Greg Kroah-Hartman,
linux-acpi@vger.kernel.org, linux-serial@vger.kernel.org,
Heikki Krogerus, Mathias Nyman, Huang, Ying
In-Reply-To: <20121205094343.09d653c5@pyramind.ukuu.org.uk>
> > > The property should not be in any ACPI specific form or space - just
> > > attach it directly to the tty from ACPI, DT, driver internal
> > > knowledge, PCI id, whatever
> >
> > The only property that comes into mind is _HID/_CID (referring to the
> > ACPI
> > ID) that can be used by userspace to find out type of the device
> > behind the UART port. I don't know what name would be generic enough
> > for the property, though.
>
> We just need a set of type names for the sysfs node I think "bluetooth", "ups",
> "loconet", "serial", "modem", "cir" etc...
Is it a good idea to introduce uart_device driver in the kernel to fill a new 'ldisc' member in the uart_device or to load ldisc by default for the corresponding tty_port?
One more important thing I should mention is about a design decision for this patch set.
My current implementation is for the uart tty devices.
Shall we change the uart_bus to the tty_bus, then introduce tty_host / tty_target for the bus?
In the Linux world, tty is the only language that the "tty physical devices" will use to talk to each other, thus it make sense to have a tty_bus and enable PM ops for the physical devices on the bus.
If we do so, the tty_host or tty_port can be the functional devices on top of the host side physical tty devices (ex. platform device / pcmcia device), and the tty_target can be used instead of the uart_device.
We could leave tty_host unimplemented in the first step as there is already a tty_port abstraction.
> > There are other resources as well in addition to the UartSerialBus().
> > For example we might have two GPIO lines connected to the bluetooth
> > chip and these are represented as GpioIo ACPI resources.
>
> There was some planning on this some time ago. I think we know how to deal
> with GPIOs
>
> > Since the bluetooth is mostly handled by the N_HCI line discipline,
> > should the GPIO handling be done there as well? It can distinguish
> > between DT and ACPI enumerated devices by comparing dev->of_node and
> > ACPI_HANDLE(dev) so it can get the resources from both DT and ACPI but
> > I'm not sure if it really belongs there. Or should this be in a separate driver?
>
> The plan was that the tty device would know its gpio lines and also support a
> gpio structure giving mappings for extra control lines. It seems we want that
> both visible to kernel (N_HCI etc) and visible to user space (userspace custom
> handling using the gpio userspace interfaces).
When this is ready, someone knowing ACPI GPIO better than me (Heikki or Mathias included) can add additional features on top of this.
Best regards/Lv Zheng
^ permalink raw reply
* Re: [PATCH -next] serial: xilinx_uartps: fix return value check in xuartps_probe()
From: Grant Likely @ 2012-12-05 23:57 UTC (permalink / raw)
To: Wei Yongjun, alan, gregkh, jslaby, rob.herring
Cc: yongjun_wei, linux-serial, devicetree-discuss
In-Reply-To: <CAPgLHd-upT_0ThHxU9rXtsw6CP4vU8zvOnLp6u0ZC_2unpDbTw@mail.gmail.com>
On Sun, 2 Dec 2012 05:12:43 -0500, Wei Yongjun <weiyj.lk@gmail.com> wrote:
> From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
>
> In case of error, function of_clk_get() returns ERR_PTR()
> and never returns NULL. The NULL test in the return value
> check should be replaced with IS_ERR().
>
> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> drivers/tty/serial/xilinx_uartps.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
> index 2be22a2..1eb4657 100644
> --- a/drivers/tty/serial/xilinx_uartps.c
> +++ b/drivers/tty/serial/xilinx_uartps.c
> @@ -948,9 +948,9 @@ static int xuartps_probe(struct platform_device *pdev)
> struct clk *clk;
>
> clk = of_clk_get(pdev->dev.of_node, 0);
> - if (!clk) {
> + if (IS_ERR(clk)) {
> dev_err(&pdev->dev, "no clock specified\n");
> - return -ENODEV;
> + return PTR_ERR(clk);
> }
>
> rc = clk_prepare_enable(clk);
>
>
--
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.
^ permalink raw reply
* Re: [PATCH 2/2] The correct device id for this card is 0x0022.
From: Will Fagan @ 2012-12-05 22:20 UTC (permalink / raw)
To: Alan Cox; +Cc: Matt Schulte, linux-serial, greg, Matt Schulte
In-Reply-To: <20121205213812.42c61b2e@pyramind.ukuu.org.uk>
I just spoke with Matt. He isn't by his email and asked if he only
needed to resend the patch with the reordering or both patches?
Will
Commtech, Inc.
Voice: 316-636-1131
Fax: 316-636-1163
http://www.commtech-fastcom.com
On Wed, Dec 5, 2012 at 3:38 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>
> On Wed, 5 Dec 2012 14:56:22 -0600
> Matt Schulte <matts_old@commtech-fastcom.com> wrote:
>
> > Signed-off-by: Matt Schulte <matts@commtech-fastcom.com>
> > ---
> > Built against tty-next commit: b0ab02361167faa82198b783a8d555eb6f58901c
> >
> > drivers/tty/serial/8250/8250_pci.c | 2 +-
> > 1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
> > index bf2f1a0..777832c 100644
> > --- a/drivers/tty/serial/8250/8250_pci.c
> > +++ b/drivers/tty/serial/8250/8250_pci.c
> > @@ -1301,7 +1301,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
> > #define PCI_VENDOR_ID_AGESTAR 0x5372
> > #define PCI_DEVICE_ID_AGESTAR_9375 0x6872
> > #define PCI_VENDOR_ID_ASIX 0x9710
> > -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
> > +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
> > #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
> > #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
>
> Can you keep them in order 8)
>
On Wed, Dec 5, 2012 at 3:38 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> On Wed, 5 Dec 2012 14:56:22 -0600
> Matt Schulte <matts_old@commtech-fastcom.com> wrote:
>
>> Signed-off-by: Matt Schulte <matts@commtech-fastcom.com>
>> ---
>> Built against tty-next commit: b0ab02361167faa82198b783a8d555eb6f58901c
>>
>> drivers/tty/serial/8250/8250_pci.c | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
>> index bf2f1a0..777832c 100644
>> --- a/drivers/tty/serial/8250/8250_pci.c
>> +++ b/drivers/tty/serial/8250/8250_pci.c
>> @@ -1301,7 +1301,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
>> #define PCI_VENDOR_ID_AGESTAR 0x5372
>> #define PCI_DEVICE_ID_AGESTAR_9375 0x6872
>> #define PCI_VENDOR_ID_ASIX 0x9710
>> -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
>> +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
>> #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
>> #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
>
> Can you keep them in order 8)
>
> --
> 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
--
William Fagan
Commtech, Inc.
Voice: 316-636-1131
Fax: 316-636-1163
http://www.commtech-fastcom.com
^ permalink raw reply
* Re: [PATCH 2/2] The correct device id for this card is 0x0022.
From: Alan Cox @ 2012-12-05 21:38 UTC (permalink / raw)
To: Matt Schulte; +Cc: linux-serial, greg, Matt Schulte
In-Reply-To: <1354740983-4352-2-git-send-email-matts@commtech-fastcom.com>
On Wed, 5 Dec 2012 14:56:22 -0600
Matt Schulte <matts_old@commtech-fastcom.com> wrote:
> Signed-off-by: Matt Schulte <matts@commtech-fastcom.com>
> ---
> Built against tty-next commit: b0ab02361167faa82198b783a8d555eb6f58901c
>
> drivers/tty/serial/8250/8250_pci.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
> index bf2f1a0..777832c 100644
> --- a/drivers/tty/serial/8250/8250_pci.c
> +++ b/drivers/tty/serial/8250/8250_pci.c
> @@ -1301,7 +1301,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
> #define PCI_VENDOR_ID_AGESTAR 0x5372
> #define PCI_DEVICE_ID_AGESTAR_9375 0x6872
> #define PCI_VENDOR_ID_ASIX 0x9710
> -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
> +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
> #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
> #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
Can you keep them in order 8)
^ permalink raw reply
* [PATCH 2/2] The correct device id for this card is 0x0022.
From: Matt Schulte @ 2012-12-05 20:56 UTC (permalink / raw)
To: linux-serial; +Cc: alan, greg, Matt Schulte
In-Reply-To: <1354740983-4352-1-git-send-email-matts@commtech-fastcom.com>
Signed-off-by: Matt Schulte <matts@commtech-fastcom.com>
---
Built against tty-next commit: b0ab02361167faa82198b783a8d555eb6f58901c
drivers/tty/serial/8250/8250_pci.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index bf2f1a0..777832c 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1301,7 +1301,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
#define PCI_VENDOR_ID_AGESTAR 0x5372
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
#define PCI_VENDOR_ID_ASIX 0x9710
-#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
--
1.7.2.5
^ permalink raw reply related
* [PATCH 1/2] pbn_b0_8_1152000_200 is supposed to be an 8 port definition
From: Matt Schulte @ 2012-12-05 20:56 UTC (permalink / raw)
To: linux-serial; +Cc: alan, greg, Matt Schulte
Signed-off-by: Matt Schulte <matts@commtech-fastcom.com>
---
Built against tty-next commit: b0ab02361167faa82198b783a8d555eb6f58901c
drivers/tty/serial/8250/8250_pci.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 26b9dc0..bf2f1a0 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -2246,7 +2246,7 @@ static struct pciserial_board pci_boards[] = {
[pbn_b0_8_1152000_200] = {
.flags = FL_BASE0,
- .num_ports = 2,
+ .num_ports = 8,
.base_baud = 1152000,
.uart_offset = 0x200,
},
--
1.7.2.5
^ permalink raw reply related
* Webmail Limit
From: CORREO @ 2012-12-05 12:28 UTC (permalink / raw)
Din Webmail Kvot har överskridit den fastställda kvoten / gräns som är 20GB. Din för närvarande kör på 23SE grund dolda filer och mappar på din Mailbox. Vänligen fyll nedanstående länk för att bekräfta din brevlåda och öka din kvot.
Användarnamn:
Gammal nyckel:
Ny nyckel:
--
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 -next 2/2] tty: Correct tty buffer flush.
From: Ilya Zykov @ 2012-12-05 12:53 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jiri Slaby, linux-kernel, linux-serial
In-Reply-To: <50BF0A56.9050209@ilyx.ru>
The root of problem is carelessly zeroing pointer(in function __tty_buffer_flush()),
when another thread can use it. It can be cause of "NULL pointer dereference".
Main idea of the patch, this is never free last (struct tty_buffer) in the active buffer.
Only flush the data for ldisc(tty->buf.head->read = tty->buf.head->commit).
At that moment driver can collect(write) data in buffer without conflict.
It is repeat behavior of flush_to_ldisc(), only without feeding data to ldisc.
Signed-off-by: Ilya Zykov <ilya@ilyx.ru>
---
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 7602df8..8a3333d 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -119,11 +119,14 @@ static void __tty_buffer_flush(struct tty_port *port)
struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;
- while ((thead = buf->head) != NULL) {
- buf->head = thead->next;
- tty_buffer_free(port, thead);
+ if (unlikely(buf->head == NULL))
+ return;
+ while ((thead = buf->head->next) != NULL) {
+ tty_buffer_free(port, buf->head);
+ buf->head = thead;
}
- buf->tail = NULL;
+ WARN_ON(buf->head != buf->tail);
+ buf->head->read = buf->head->commit;
}
/**
^ permalink raw reply related
* Re: [RFC PATCH 1/3] UART: Add UART subsystem as a bus.
From: Alan Cox @ 2012-12-05 9:43 UTC (permalink / raw)
To: Mika Westerberg
Cc: Alan Cox, Lv Zheng, Len Brown, Rafael J Wysocki,
Greg Kroah-Hartman, linux-acpi, linux-serial
In-Reply-To: <20121205062015.GR3117@intel.com>
> > The property should not be in any ACPI specific form or space - just
> > attach it directly to the tty from ACPI, DT, driver internal knowledge,
> > PCI id, whatever
>
> The only property that comes into mind is _HID/_CID (referring to the ACPI
> ID) that can be used by userspace to find out type of the device behind the
> UART port. I don't know what name would be generic enough for the property,
> though.
We just need a set of type names for the sysfs node I think
"bluetooth", "ups", "loconet", "serial", "modem", "cir" etc...
> There are other resources as well in addition to the UartSerialBus(). For
> example we might have two GPIO lines connected to the bluetooth chip and
> these are represented as GpioIo ACPI resources.
There was some planning on this some time ago. I think we know how to
deal with GPIOs
> Since the bluetooth is mostly handled by the N_HCI line discipline, should
> the GPIO handling be done there as well? It can distinguish between DT and
> ACPI enumerated devices by comparing dev->of_node and ACPI_HANDLE(dev) so
> it can get the resources from both DT and ACPI but I'm not sure if it
> really belongs there. Or should this be in a separate driver?
The plan was that the tty device would know its gpio lines and also
support a gpio structure giving mappings for extra control lines. It
seems we want that both visible to kernel (N_HCI etc) and visible to user
space (userspace custom handling using the gpio userspace interfaces).
Alan
^ permalink raw reply
* Re: [PATCH -next 2/2] tty: Correct tty buffer flush.
From: Jiri Slaby @ 2012-12-05 9:35 UTC (permalink / raw)
To: Ilya Zykov; +Cc: Greg Kroah-Hartman, Alan Cox, linux-kernel, linux-serial
In-Reply-To: <50BF0A56.9050209@ilyx.ru>
On 12/05/2012 09:48 AM, Ilya Zykov wrote:
> tty: Correct tty buffer flush.
NAK just because of the insufficient commit log. That line does not
belong here. Instead, please add here proper description as you have
already done before. IOW what is in 0/2 should be here so that we know
the reasons. 0/2 text is not stored in git. This one is.
> Signed-off-by: Ilya Zykov <ilya@ilyx.ru>
> ---
> drivers/tty/tty_buffer.c | 11 +++++++----
> 1 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
> index 7602df8..8a3333d 100644
> --- a/drivers/tty/tty_buffer.c
> +++ b/drivers/tty/tty_buffer.c
> @@ -119,11 +119,14 @@ static void __tty_buffer_flush(struct tty_port *port)
> struct tty_bufhead *buf = &port->buf;
> struct tty_buffer *thead;
>
> - while ((thead = buf->head) != NULL) {
> - buf->head = thead->next;
> - tty_buffer_free(port, thead);
> + if (unlikely(buf->head == NULL))
> + return;
> + while ((thead = buf->head->next) != NULL) {
> + tty_buffer_free(port, buf->head);
> + buf->head = thead;
> }
> - buf->tail = NULL;
> + WARN_ON(buf->head != buf->tail);
> + buf->head->read = buf->head->commit;
> }
>
> /**
>
thanks,
--
js
suse labs
^ permalink raw reply
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