* [PATCH 5/5] serial: 8250_dw: Set FIFO size dynamically
From: Heikki Krogerus @ 2012-11-28 12:48 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, LKML
In-Reply-To: <1354106924-11013-1-git-send-email-heikki.krogerus@linux.intel.com>
Designware UART provides optional Component Parameter
Register that lists most of the capabilities of the UART,
including FIFO size. This uses that register to set FIFO
size for the port before registering it.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 57 ++++++++++++++++++++++++++++++++++---
1 file changed, 53 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index bfbfb07..4c5e60a 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -25,6 +25,28 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+/* Offsets for the DesignWare specific registers */
+#define DW_UART_USR 0x1f /* UART Status Register */
+#define DW_UART_CPR 0xf4 /* Component Parameter Register */
+#define DW_UART_UCV 0xf8 /* UART Component Version */
+
+/* Component Parameter Register bits */
+#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
+#define DW_UART_CPR_AFCE_MODE (1 << 4)
+#define DW_UART_CPR_THRE_MODE (1 << 5)
+#define DW_UART_CPR_SIR_MODE (1 << 6)
+#define DW_UART_CPR_SIR_LP_MODE (1 << 7)
+#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8)
+#define DW_UART_CPR_FIFO_ACCESS (1 << 9)
+#define DW_UART_CPR_FIFO_STAT (1 << 10)
+#define DW_UART_CPR_SHADOW (1 << 11)
+#define DW_UART_CPR_ENCODED_PARMS (1 << 12)
+#define DW_UART_CPR_DMA_EXTRA (1 << 13)
+#define DW_UART_CPR_FIFO_MODE (0xff << 16)
+/* Helper for fifo size calculation */
+#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
+
+
struct dw8250_data {
int last_lcr;
int line;
@@ -66,9 +88,6 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
return readl(p->membase + offset);
}
-/* Offset for the DesignWare's UART Status Register. */
-#define UART_USR 0x1f
-
static int dw8250_handle_irq(struct uart_port *p)
{
struct dw8250_data *d = p->private_data;
@@ -78,7 +97,7 @@ static int dw8250_handle_irq(struct uart_port *p)
return 1;
} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
/* Clear the USR and write the LCR again. */
- (void)p->serial_in(p, UART_USR);
+ (void)p->serial_in(p, DW_UART_USR);
p->serial_out(p, d->last_lcr, UART_LCR);
return 1;
@@ -119,6 +138,34 @@ static int __devinit dw8250_probe_of(struct uart_port *p)
return 0;
}
+static void __devinit dw8250_setup_port(struct uart_8250_port *up)
+{
+ struct uart_port *p = &up->port;
+ u32 reg = readl(p->membase + DW_UART_UCV);
+
+ /*
+ * If the Component Version Register returns zero, we know that
+ * ADDITIONAL_FEATURES are not enabled. No need to go any further.
+ */
+ if (!reg || (reg & 0xff) != '*')
+ return;
+
+ dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
+ (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
+
+ reg = readl(p->membase + DW_UART_CPR);
+ if (!reg)
+ return;
+
+ /* Select the type based on fifo */
+ if (reg & DW_UART_CPR_FIFO_MODE) {
+ p->type = PORT_16550A;
+ p->flags |= UPF_FIXED_TYPE;
+ p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
+ up->tx_loadsz = p->fifosize;
+ }
+}
+
static int __devinit dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {};
@@ -156,6 +203,8 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
return -ENODEV;
}
+ dw8250_setup_port(&uart);
+
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/5] serial: 8250_dw: Move device tree code to separate function
From: Heikki Krogerus @ 2012-11-28 12:48 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, LKML
In-Reply-To: <1354106924-11013-1-git-send-email-heikki.krogerus@linux.intel.com>
Trivial cleanup. This makes it easier to add different
methods to enumerate the device, for example ACPI 5.0
enumeration.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 76 ++++++++++++++++++++++---------------
1 file changed, 46 insertions(+), 30 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 8394f85..bfbfb07 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -87,25 +87,51 @@ static int dw8250_handle_irq(struct uart_port *p)
return 0;
}
+static int __devinit dw8250_probe_of(struct uart_port *p)
+{
+ struct device_node *np = p->dev->of_node;
+ u32 val;
+
+ if (!of_property_read_u32(np, "reg-io-width", &val)) {
+ switch (val) {
+ case 1:
+ break;
+ case 4:
+ p->iotype = UPIO_MEM32;
+ p->serial_in = dw8250_serial_in32;
+ p->serial_out = dw8250_serial_out32;
+ break;
+ default:
+ dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
+ return -EINVAL;
+ }
+ }
+
+ if (!of_property_read_u32(np, "reg-shift", &val))
+ p->regshift = val;
+
+ if (of_property_read_u32(np, "clock-frequency", &val)) {
+ dev_err(p->dev, "no clock-frequency property set\n");
+ return -EINVAL;
+ }
+ p->uartclk = val;
+
+ return 0;
+}
+
static int __devinit dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- struct device_node *np = pdev->dev.of_node;
- u32 val;
struct dw8250_data *data;
+ int err;
if (!regs || !irq) {
dev_err(&pdev->dev, "no registers/irq defined\n");
return -EINVAL;
}
- 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.irq = irq->start;
@@ -121,30 +147,20 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
uart.port.iotype = UPIO_MEM;
uart.port.serial_in = dw8250_serial_in;
uart.port.serial_out = dw8250_serial_out;
- if (!of_property_read_u32(np, "reg-io-width", &val)) {
- switch (val) {
- case 1:
- break;
- case 4:
- uart.port.iotype = UPIO_MEM32;
- uart.port.serial_in = dw8250_serial_in32;
- uart.port.serial_out = dw8250_serial_out32;
- break;
- default:
- dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
- val);
- return -EINVAL;
- }
+
+ if (pdev->dev.of_node) {
+ err = dw8250_probe_of(&uart.port);
+ if (err)
+ return err;
+ } else {
+ return -ENODEV;
}
- if (!of_property_read_u32(np, "reg-shift", &val))
- uart.port.regshift = val;
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- if (of_property_read_u32(np, "clock-frequency", &val)) {
- dev_err(&pdev->dev, "no clock-frequency property set\n");
- return -EINVAL;
- }
- uart.port.uartclk = val;
+ uart.port.private_data = data;
data->line = serial8250_register_8250_port(&uart);
if (data->line < 0)
@@ -164,7 +180,7 @@ static int __devexit dw8250_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id dw8250_match[] = {
+static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "snps,dw-apb-uart" },
{ /* Sentinel */ }
};
@@ -174,7 +190,7 @@ static struct platform_driver dw8250_platform_driver = {
.driver = {
.name = "dw-apb-uart",
.owner = THIS_MODULE,
- .of_match_table = dw8250_match,
+ .of_match_table = dw8250_of_match,
},
.probe = dw8250_probe,
.remove = __devexit_p(dw8250_remove),
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/5] serial: 8250_dw: Map IO memory
From: Heikki Krogerus @ 2012-11-28 12:48 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, LKML
In-Reply-To: <1354106924-11013-1-git-send-email-heikki.krogerus@linux.intel.com>
This needs to be done in order to later access the
Designware specific registers.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 8d45be5..8394f85 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -111,10 +111,13 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
uart.port.irq = irq->start;
uart.port.handle_irq = dw8250_handle_irq;
uart.port.type = PORT_8250;
- uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
- UPF_FIXED_PORT;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
uart.port.dev = &pdev->dev;
+ uart.port.membase = ioremap(regs->start, regs->end - regs->start);
+ if (!uart.port.membase)
+ return -ENOMEM;
+
uart.port.iotype = UPIO_MEM;
uart.port.serial_in = dw8250_serial_in;
uart.port.serial_out = dw8250_serial_out;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/5] serial: 8250: Allow drivers to deliver capabilities
From: Heikki Krogerus @ 2012-11-28 12:48 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, LKML
In-Reply-To: <1354106924-11013-1-git-send-email-heikki.krogerus@linux.intel.com>
Modern UARTs are able to provide information about their
capabilities such as FIFO size. This allows the drivers to
deliver this information to 8250.c when they are registering
ports.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
drivers/tty/serial/8250/8250.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 3ba4234..7dd131e 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1906,9 +1906,12 @@ static int serial8250_startup(struct uart_port *port)
if (port->type == PORT_8250_CIR)
return -ENODEV;
- port->fifosize = uart_config[up->port.type].fifo_size;
- up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
- up->capabilities = uart_config[up->port.type].flags;
+ if (!port->fifosize)
+ port->fifosize = uart_config[port->type].fifo_size;
+ if (!up->tx_loadsz)
+ up->tx_loadsz = uart_config[port->type].tx_loadsz;
+ if (!up->capabilities)
+ up->capabilities = uart_config[port->type].flags;
up->mcr = 0;
if (port->iotype != up->cur_iotype)
@@ -2739,9 +2742,12 @@ static void
serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
{
up->port.type = type;
- up->port.fifosize = uart_config[type].fifo_size;
- up->capabilities = uart_config[type].flags;
- up->tx_loadsz = uart_config[type].tx_loadsz;
+ if (!up->port.fifosize)
+ up->port.fifosize = uart_config[type].fifo_size;
+ if (!up->tx_loadsz)
+ up->tx_loadsz = uart_config[type].tx_loadsz;
+ if (!up->capabilities)
+ up->capabilities = uart_config[type].flags;
}
static void __init
@@ -3175,6 +3181,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart->bugs = up->bugs;
uart->port.mapbase = up->port.mapbase;
uart->port.private_data = up->port.private_data;
+ uart->port.fifosize = up->port.fifosize;
+ uart->tx_loadsz = up->tx_loadsz;
+ uart->capabilities = up->capabilities;
+
if (up->port.dev)
uart->port.dev = up->port.dev;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/5] serial: 8250_dw: Don't use UPF_FIXED_TYPE
From: Heikki Krogerus @ 2012-11-28 12:48 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, LKML
In-Reply-To: <1354106924-11013-1-git-send-email-heikki.krogerus@linux.intel.com>
Allow 8250.c to determine the port type for us. This allows
the driver take advantage of FIFO on Designware UARTs that
have it.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index c3b2ec0..8d45be5 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -112,7 +112,7 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
uart.port.handle_irq = dw8250_handle_irq;
uart.port.type = PORT_8250;
uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
- UPF_FIXED_PORT | UPF_FIXED_TYPE;
+ UPF_FIXED_PORT;
uart.port.dev = &pdev->dev;
uart.port.iotype = UPIO_MEM;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/5] serial: 8250: 8250_dw changes and dynamic capabilities
From: Heikki Krogerus @ 2012-11-28 12:48 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, LKML
Hi,
These are mainly small changes to 8250_dw.c. The interesting patch is
probable the addition to 8250.c that would allow the drivers to
deliver their UART's capabilities when they are registering ports.
Heikki Krogerus (5):
serial: 8250: Allow drivers to deliver capabilities
serial: 8250_dw: Don't use UPF_FIXED_TYPE
serial: 8250_dw: Map IO memory
serial: 8250_dw: Move device tree code to separate function
serial: 8250_dw: Set FIFO size dynamically
drivers/tty/serial/8250/8250.c | 22 ++++--
drivers/tty/serial/8250/8250_dw.c | 140 +++++++++++++++++++++++++++----------
2 files changed, 120 insertions(+), 42 deletions(-)
--
1.7.10.4
^ permalink raw reply
* Re: Fwd: [PULL REQUEST] Tweak to support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
From: Alexey Pelykh @ 2012-11-28 9:05 UTC (permalink / raw)
To: Greg KH, Alan Cox; +Cc: linux-serial
In-Reply-To: <20121128004204.GB3857@kroah.com>
Original table in OMAP TRM named "UART Mode Baud Rates, Divisor
Values, and Error Rates" determines modes not for all common baud
rates. E.g. for 1000000 baud rate mode should be 16x, but according to
that table it's determined as 13x. According to current implementation
of mode
divisor selection, after requesting 1000000 baudrate from driver,
later one will configure chip to use MODE13 divisor. Assuming 48Mhz as
common UART clock speed, MODE13 divisor will effectively give 1230769
baudrate, what is quite far from desired 1000000 baudrate. While with
MODE16 divisor, chip will produce exact 1000000 baudrate.
In old driver that served UART devices (8250.c and serial_core.c) this
divisor could have been configured by user-space program, but in
omap_serial.c driver implementation this ability was not implemented
(afaik, by design) thus disallowing proper usage of MODE16-compatible
baudrates.
Changes: I've fixed styling errors using ./scripts/checkpatch.pl
Signed-off-by: Alexey Pelykh <alexey.pelykh@gmail.com>
The following changes since commit 77b67063bb6bce6d475e910d3b886a606d0d91f7:
Linux 3.7-rc5 (2012-11-11 13:44:33 +0100)
are available in the git repository at:
git://github.com/alexey-pelykh/linux.git omap_serial_mode_fix
for you to fetch changes up to cf827bb4057fdcdaeac20b95b01c29c068109185:
Tweak to support 1Mbaud and similar baudrates that require Mode16
instead of Mode13 (2012-11-12 19:29:27 +0200)
----------------------------------------------------------------
Alexey Pelykh (1):
Tweak to support 1Mbaud and similar baudrates that require
Mode16 instead of Mode13
drivers/tty/serial/omap-serial.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6d3d26a..6d567dd 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -182,24 +182,42 @@ static void serial_omap_enable_wakeup(struct
uart_omap_port *up, bool enable)
}
/*
+ * serial_omap_baud_is_mode16 - check if baud rate is MODE16X
+ * @port: uart port info
+ * @baud: baudrate for which mode needs to be determined
+ *
+ * Returns true if baud rate is MODE16X and false if MODE13X
+ * Original table in OMAP TRM named "UART Mode Baud Rates, Divisor Values,
+ * and Error Rates" determines modes not for all common baud rates.
+ * E.g. for 1000000 baud rate mode must be 16x, but according to that
+ * table it's determined as 13x.
+ */
+static bool
+serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
+{
+ unsigned int n13 = port->uartclk / (13 * baud);
+ unsigned int n16 = port->uartclk / (16 * baud);
+ int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
+ int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
+ if (baudAbsDiff13 < 0)
+ baudAbsDiff13 = -baudAbsDiff13;
+ if (baudAbsDiff16 < 0)
+ baudAbsDiff16 = -baudAbsDiff16;
+
+ return (baudAbsDiff13 > baudAbsDiff16);
+}
+
+/*
* serial_omap_get_divisor - calculate divisor value
* @port: uart port info
* @baud: baudrate for which divisor needs to be calculated.
- *
- * We have written our own function to get the divisor so as to support
- * 13x mode. 3Mbps Baudrate as an different divisor.
- * Reference OMAP TRM Chapter 17:
- * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
- * referring to oversampling - divisor value
- * baudrate 460,800 to 3,686,400 all have divisor 13
- * except 3,000,000 which has divisor value 16
*/
static unsigned int
serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
{
unsigned int divisor;
- if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+ if (!serial_omap_baud_is_mode16(port, baud))
divisor = 13;
else
divisor = 16;
@@ -893,7 +911,7 @@ serial_omap_set_termios(struct uart_port *port,
struct ktermios *termios,
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, cval);
- if (baud > 230400 && baud != 3000000)
+ if (!serial_omap_baud_is_mode16(port, baud))
up->mdr1 = UART_OMAP_MDR1_13X_MODE;
else
up->mdr1 = UART_OMAP_MDR1_16X_MODE;
^ permalink raw reply related
* Re: Comments requested: driver for Quatech PCI serial cards
From: Jonathan Woithe @ 2012-11-28 2:29 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-serial, jwoithe
In-Reply-To: <20121115155347.4be3dce8@pyramind.ukuu.org.uk>
On Thu, Nov 15, 2012 at 03:53:47PM +0000, Alan Cox wrote:
> > Unfortunately we need the RS422 stuff - that's the reason for using the
> > DSC-200/300 card.
> >
> > Thanks for the comments and feedback - I'll take another look at things in
> > the light of the information. If the functionality we require requires a
> > significant amount of new code to be written, I suspect that the work will
> > be deemed too time consuming by those who call the shots. We'll see.
>
> First guess at what you need except for the RS422 registers is attached.
> To get the RS422 features working needs the tool tracing (or driver
> printks adding) to see what QMCR and QOPR bits map to which RS422
> features.
>
> Given that if you just force the bits you want in with the RS422 warning I
> expect it'll just work for your case and should then be trivial to add the
> ioctl.
Apologies for the delay in getting back to this.
With a minor change (the port IO base must be set prior to calling
pci_quatech_clock() and pci_quatech_rs422() in pci_quatech_setup()) this
seems to do the job for us (with a DSC-200/300 card). As it turns out, the
card configuration we need happens to match the power-on default state of
the card when the jumpers are not in use, so no further manipulation is
required at this stage. Revised patch is below, against the tty git tree.
I also tweaked the warning a little to make it clearer that it is the
software control of RS422 features that aren't supported. If the defaults
are fine (or the hardware jumpers are used to control the features) then
RS422 will work just fine.
So far as getting something working for our case, the patch below is all
that is required. I do know the QMCR and QOPR bit map details for at least
the DSC-200/300 card as it's more or less described in the manual. I will
try to prepare a second patch which at least creates the necessary defines
for these in the next few days.
With regard to the ioctl, should this be an implementation of the ioctl
provided by the old out-of-tree driver, or is there an established
standard/example which I should write against instead?
jonathan
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 17b7d26..43c6b4f 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1040,6 +1040,253 @@ static int pci_asix_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx);
}
+/* Quatech devices have their own extra interface features */
+
+struct quatech_feature {
+ u16 devid;
+ bool amcc;
+};
+
+#define QPCR_TEST_FOR1 0x3F
+#define QPCR_TEST_GET1 0x00
+#define QPCR_TEST_FOR2 0x40
+#define QPCR_TEST_GET2 0x40
+#define QPCR_TEST_FOR3 0x80
+#define QPCR_TEST_GET3 0x40
+#define QPCR_TEST_FOR4 0xC0
+#define QPCR_TEST_GET4 0x80
+
+#define QOPR_CLOCK_X1 0x0000
+#define QOPR_CLOCK_X2 0x0001
+#define QOPR_CLOCK_X4 0x0002
+#define QOPR_CLOCK_X8 0x0003
+#define QOPR_CLOCK_RATE_MASK 0x0003
+
+
+static struct quatech_feature quatech_cards[] = {
+ { PCI_DEVICE_ID_QUATECH_QSC100, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSC100, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSC100E, 0 },
+ { PCI_DEVICE_ID_QUATECH_DSC200, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSC200E, 0 },
+ { PCI_DEVICE_ID_QUATECH_ESC100D, 1 },
+ { PCI_DEVICE_ID_QUATECH_ESC100M, 1 },
+ { PCI_DEVICE_ID_QUATECH_QSCP100, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSCP100, 1 },
+ { PCI_DEVICE_ID_QUATECH_QSCP200, 1 },
+ { PCI_DEVICE_ID_QUATECH_DSCP200, 1 },
+ { PCI_DEVICE_ID_QUATECH_ESCLP100, 0 },
+ { PCI_DEVICE_ID_QUATECH_QSCLP100, 0 },
+ { PCI_DEVICE_ID_QUATECH_DSCLP100, 0 },
+ { PCI_DEVICE_ID_QUATECH_SSCLP100, 0 },
+ { PCI_DEVICE_ID_QUATECH_QSCLP200, 0 },
+ { PCI_DEVICE_ID_QUATECH_DSCLP200, 0 },
+ { PCI_DEVICE_ID_QUATECH_SSCLP200, 0 },
+ { PCI_DEVICE_ID_QUATECH_SPPXP_100, 0 },
+ { 0, }
+};
+
+static int pci_quatech_amcc(u16 devid)
+{
+ struct quatech_feature *qf = &quatech_cards[0];
+ while (qf->devid) {
+ if (qf->devid == devid)
+ return qf->amcc;
+ qf++;
+ }
+ pr_err("quatech: unknown port type '0x%04X'.\n", devid);
+ return 0;
+};
+
+static int pci_quatech_rqopr(struct uart_8250_port *port)
+{
+ unsigned long base = port->port.iobase;
+ u8 LCR, val;
+
+ LCR = inb(base + UART_LCR);
+ outb(0xBF, base + UART_LCR);
+ val = inb(base + UART_SCR);
+ outb(LCR, base + UART_LCR);
+ return val;
+}
+
+static void pci_quatech_wqopr(struct uart_8250_port *port, u8 qopr)
+{
+ unsigned long base = port->port.iobase;
+ u8 LCR, val;
+
+ LCR = inb(base + UART_LCR);
+ outb(0xBF, base + UART_LCR);
+ val = inb(base + UART_SCR);
+ outb(qopr, base + UART_SCR);
+ outb(LCR, base + UART_LCR);
+}
+
+static int pci_quatech_rqmcr(struct uart_8250_port *port)
+{
+ unsigned long base = port->port.iobase;
+ u8 LCR, val, qmcr;
+
+ LCR = inb(base + UART_LCR);
+ outb(0xBF, base + UART_LCR);
+ val = inb(base + UART_SCR);
+ outb(val | 0x10, base + UART_SCR);
+ qmcr = inb(base + UART_MCR);
+ outb(val, base + UART_SCR);
+ outb(LCR, base + UART_LCR);
+
+ return qmcr;
+}
+
+static void pci_quatech_wqmcr(struct uart_8250_port *port, u8 qmcr)
+{
+ unsigned long base = port->port.iobase;
+ u8 LCR, val;
+
+ LCR = inb(base + UART_LCR);
+ outb(0xBF, base + UART_LCR);
+ val = inb(base + UART_SCR);
+ outb(val | 0x10, base + UART_SCR);
+ outb(qmcr, base + UART_MCR);
+ outb(val, base + UART_SCR);
+ outb(LCR, base + UART_LCR);
+}
+
+static int pci_quatech_has_qmcr(struct uart_8250_port *port)
+{
+ unsigned long base = port->port.iobase;
+ u8 LCR, val;
+
+ LCR = inb(base + UART_LCR);
+ outb(0xBF, base + UART_LCR);
+ val = inb(base + UART_SCR);
+ if (val & 0x20) {
+ outb(0x80, UART_LCR);
+ if (!(inb(UART_SCR) & 0x20)) {
+ outb(LCR, base + UART_LCR);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int pci_quatech_test(struct uart_8250_port *port)
+{
+ u8 reg;
+ u8 qopr = pci_quatech_rqopr(port);
+ pci_quatech_wqopr(port, qopr & QPCR_TEST_FOR1);
+ reg = pci_quatech_rqopr(port) & 0xC0;
+ if (reg != QPCR_TEST_GET1)
+ return -EINVAL;
+ pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR2);
+ reg = pci_quatech_rqopr(port) & 0xC0;
+ if (reg != QPCR_TEST_GET2)
+ return -EINVAL;
+ pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR3);
+ reg = pci_quatech_rqopr(port) & 0xC0;
+ if (reg != QPCR_TEST_GET3)
+ return -EINVAL;
+ pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR4);
+ reg = pci_quatech_rqopr(port) & 0xC0;
+ if (reg != QPCR_TEST_GET4)
+ return -EINVAL;
+
+ pci_quatech_wqopr(port, qopr);
+ return 0;
+}
+
+static int pci_quatech_clock(struct uart_8250_port *port)
+{
+ u8 qopr, reg, set;
+ unsigned long clock;
+
+ if (pci_quatech_test(port) < 0)
+ return 1843200;
+
+ qopr = pci_quatech_rqopr(port);
+
+ pci_quatech_wqopr(port, qopr & ~QOPR_CLOCK_X8);
+ reg = pci_quatech_rqopr(port);
+ if (reg & QOPR_CLOCK_X8) {
+ clock = 1843200;
+ goto out;
+ }
+ pci_quatech_wqopr(port, qopr | QOPR_CLOCK_X8);
+ reg = pci_quatech_rqopr(port);
+ if (!(reg & QOPR_CLOCK_X8)) {
+ clock = 1843200;
+ goto out;
+ }
+ reg &= QOPR_CLOCK_X8;
+ if (reg == QOPR_CLOCK_X2) {
+ clock = 3685400;
+ set = QOPR_CLOCK_X2;
+ } else if (reg == QOPR_CLOCK_X4) {
+ clock = 7372800;
+ set = QOPR_CLOCK_X4;
+ } else if (reg == QOPR_CLOCK_X8) {
+ clock = 14745600;
+ set = QOPR_CLOCK_X8;
+ } else {
+ clock = 1843200;
+ set = QOPR_CLOCK_X1;
+ }
+ qopr &= ~QOPR_CLOCK_RATE_MASK;
+ qopr |= set;
+
+out:
+ pci_quatech_wqopr(port, qopr);
+ return clock;
+}
+
+static int pci_quatech_rs422(struct uart_8250_port *port)
+{
+ u8 qmcr;
+ int rs422 = 0;
+
+ if (!pci_quatech_has_qmcr(port))
+ return 0;
+ qmcr = pci_quatech_rqmcr(port);
+ pci_quatech_wqmcr(port, 0xFF);
+ if (pci_quatech_rqmcr(port))
+ rs422 = 1;
+ pci_quatech_wqmcr(port, qmcr);
+ return rs422;
+}
+
+static int pci_quatech_init(struct pci_dev *dev)
+{
+ if (pci_quatech_amcc(dev->device)) {
+ unsigned long base = pci_resource_start(dev, 0);
+ if (base) {
+ u32 tmp;
+ outl(inl(base + 0x38), base + 0x38);
+ tmp = inl(base + 0x3c);
+ outl(tmp | 0x01000000, base + 0x3c);
+ outl(tmp, base + 0x3c);
+ }
+ }
+ return 0;
+}
+
+static int pci_quatech_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ /* Needed by pci_quatech calls below */
+ port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags));
+ /* Set up the clocking */
+ port->port.uartclk = pci_quatech_clock(port);
+ /* For now just warn about RS422 */
+ if (pci_quatech_rs422(port))
+ pr_warn( "quatech: software control of RS422 features not currently supported.\n");
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static void __devexit pci_quatech_exit(struct pci_dev *dev)
+{
+}
+
static int pci_default_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@@ -1503,6 +1750,16 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit),
},
+ /* Quatech */
+ {
+ .vendor = PCI_VENDOR_ID_QUATECH,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_quatech_init,
+ .setup = pci_quatech_setup,
+ .exit = __devexit_p(pci_quatech_exit),
+ },
/*
* SBS Technologies, Inc., PMC-OCTALPRO 232
*/
@@ -3257,18 +3514,70 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
0x10b5, 0x106a, 0, 0,
pbn_plx_romulus },
+ /*
+ * Quatech cards. These actually have configurable clocks but for
+ * now we just use the default.
+ *
+ * 100 series are RS232, 200 series RS422,
+ */
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_4_115200 },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_4_115200 },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_8_115200 },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_8_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_4_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_4_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b1_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_4_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_1_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_4_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_2_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_1_115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESCLP100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_8_115200 },
+
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
0, 0,
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 9d36b82..ce45006 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1867,8 +1867,23 @@
#define PCI_VENDOR_ID_QUATECH 0x135C
#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010
#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020
+#define PCI_DEVICE_ID_QUATECH_DSC200 0x0030
+#define PCI_DEVICE_ID_QUATECH_QSC200 0x0040
#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050
#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060
+#define PCI_DEVICE_ID_QUATECH_QSCP100 0x0120
+#define PCI_DEVICE_ID_QUATECH_DSCP100 0x0130
+#define PCI_DEVICE_ID_QUATECH_QSCP200 0x0140
+#define PCI_DEVICE_ID_QUATECH_DSCP200 0x0150
+#define PCI_DEVICE_ID_QUATECH_QSCLP100 0x0170
+#define PCI_DEVICE_ID_QUATECH_DSCLP100 0x0180
+#define PCI_DEVICE_ID_QUATECH_DSC100E 0x0181
+#define PCI_DEVICE_ID_QUATECH_SSCLP100 0x0190
+#define PCI_DEVICE_ID_QUATECH_QSCLP200 0x01A0
+#define PCI_DEVICE_ID_QUATECH_DSCLP200 0x01B0
+#define PCI_DEVICE_ID_QUATECH_DSC200E 0x01B1
+#define PCI_DEVICE_ID_QUATECH_SSCLP200 0x01C0
+#define PCI_DEVICE_ID_QUATECH_ESCLP100 0x01E0
#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
#define PCI_VENDOR_ID_SEALEVEL 0x135e
^ permalink raw reply related
* Re: [PATCH v2 1/1] staging: fwserial: Add TTY-over-Firewire serial driver
From: Peter Hurley @ 2012-11-28 1:00 UTC (permalink / raw)
To: Stefan Richter
Cc: Greg Kroah-Hartman, Alan Cox, linux-kernel, devel,
linux1394-devel, linux-serial
In-Reply-To: <20121128005846.0f1d4d5e@stein>
On Wed, 2012-11-28 at 00:58 +0100, Stefan Richter wrote:
> On Nov 27 Peter Hurley wrote:
> > > > Currently, firewire-net sets an arbitrary address handler length of
> > > > 4096. This works because the largest AR packet size the current
> > > > firewire-ohci driver handles is 4096 (value of MAX_ASYNC_PAYLOAD) +
> > > > header/trailer. Note that firewire-ohci does not limit card->max_receive
> > > > to this value.
> > > >
> > > > So if the ohci driver changes to handle 8K+ AR packets and the hardware
> > > > supports it, these address handler windows will be too small.
> > >
> > > While the IEEE 1394:2008 link layer specification (section 6) provides for
> > > asynchronous packet payloads of up to 16384 bytes (table 6-4), the IEEE
> > > 1394 beta mode port specification (section 13) only allows up to 4096
> > > bytes (table 16-18). And alpha mode is of course limited to 2048 bytes.
> > >
> > > So, asynchronous packet payloads greater than 4096 bytes are out of scope
> > > of the current revision of IEEE 1394.
> >
> > You should look at this 1394ta.org video
> > http://www.youtube.com/watch?v=xVXNvXHNQTY of DAP Technologies S1600
> > OHCI controllers running S1600 cameras using beta cables.
>
> I don't know the details of their implementation, but I suppose they conform
> with the 1394 beta mode port specification. Which in turn means that their
> S1600 solution (and by extrapolation, their S3200 prototypes) comply with a
> maximum asynchronous packet payload of 4096 bytes. Citing IEEE 1394-2008:
>
> >>>
> Table 16-18———Maximum payload size for Beta data packets
> Data rate | Maximum asynchronous payload size | Maximum isochronous payload
> | (bytes) | (bytes)
> ----------+-----------------------------------+----------------------------
> S100 | 512 | 1024
> S200 | 1024 | 2048
> S400 | 2048 | 4096
> S800 | 4096 | 8192
> S1600 | 4096 | 16384
> S3200 | 4096 | 32768
> <<<
>
> (Alpha mode payload limits are the same as the S100...S400 subset of beta mode.
> In IEEE 1394b-2002, the table number is 16-3.)
>
> You can of course define registers (or better termed: buffers) which are larger
> than what can be atomically read or written, or atomically compared-swapped;
> IOW which are larger than what can be accessed in a single transaction, if such
> registers or buffers are useful. But if you particularly need a register which
> is just large enough to accommodate the largest possible inbound block write
> transaction which complies with IEEE 1394, and you don't know the peer's
> capability and the speeds of all intermediary cable hops, then
> fw_card.max_receive is the number that you need. Or you ignore the cards actual
> capability and just allocate 4096 bytes.
Thanks for the clarification. I need to update
link_speed_to_max_payload() now. ;)
Plus I should just renew my IEEE membership so I can get the 1394-2008
spec without having to saw my arm off.
--
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: Fwd: [PULL REQUEST] Tweak to support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
From: Greg KH @ 2012-11-28 0:42 UTC (permalink / raw)
To: Alexey Pelykh; +Cc: linux-serial
In-Reply-To: <CAOmKuSrQW1j_tmQNbXMO-GUH7zrUR0WR3K4rJNok=2LZmRKVYg@mail.gmail.com>
On Tue, Nov 27, 2012 at 11:56:06PM +0200, Alexey Pelykh wrote:
> Hello everyone,
>
> Original table in OMAP TRM named "UART Mode Baud Rates, Divisor
> Values, and Error Rates" determines modes not for all common baud
> rates. E.g. for 1000000 baud rate mode should be 16x, but according to
> that table it's determined as 13x. According to current implementation
> of mode
> divisor selection, after requesting 1000000 baudrate from driver,
> later one will configure chip to use MODE13 divisor. Assuming 48Mhz as
> common UART clock speed, MODE13 divisor will effectively give 1230769
> baudrate, what is quite far from desired 1000000 baudrate. While with
> MODE16 divisor, chip will produce exact 1000000 baudrate.
>
> In old driver that served UART devices (8250.c and serial_core.c) this
> divisor could have been configured by user-space program, but in
> omap_serial.c driver implementation this ability was not implemented
> (afaik, by design) thus disallowing proper usage of MODE16-compatible
> baudrates.
>
> Best regards,
> Alexey Pelykh
>
> The following changes since commit 77b67063bb6bce6d475e910d3b886a606d0d91f7:
>
> Linux 3.7-rc5 (2012-11-11 13:44:33 +0100)
>
> are available in the git repository at:
>
> git://github.com/alexey-pelykh/linux.git omap_serial_mode_fix
>
> for you to fetch changes up to cf827bb4057fdcdaeac20b95b01c29c068109185:
>
> Tweak to support 1Mbaud and similar baudrates that require Mode16
> instead of Mode13 (2012-11-12 19:29:27 +0200)
Sorry, I can't take a git pull request for a single patch, please just
send it in an email (the patch that is), with the correct signed-off-by:
information, as described in Documentation/SubmittingPatches, and I will
be glad to queue it up.
thanks,
greg k-h
^ permalink raw reply
* [PATCH] tty: Correct tty buffer flushing.
From: Ilya Zykov @ 2012-11-28 0:28 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Jiri Slaby, Alan Cox, linux-kernel, linux-serial, ilya
CANCEL - [PATCH] tty: hold lock across tty buffer finding and buffer filling.
commit f8f72f047b96c6c8b13f6e3ba53fa6feb4266813
The commit above very dirty, has many degradation on SMP systems, because take
spinlock on long time, and not resolve problem with tty_prepare_string*()(Jiri Slaby).
We lose all advantage from the use of flip buffer.
The root of problem it use carelessly buffer flushing, then another thread can write to it.
This patch resolve this problem and doesn't let lose advantage from flip buffer use.
Before use need REVERT commit f8f72f047b96c6c8b13f6e3ba53fa6feb4266813.
Signed-off-by: Ilya Zykov <ilya@ilyx.ru>
---
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c9b7cd..4f02f9c 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -114,11 +114,14 @@ static void __tty_buffer_flush(struct tty_struct *tty)
{
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- tty_buffer_free(tty, thead);
+ if (tty->buf.head == NULL)
+ return;
+ while ((thead = tty->buf.head->next) != NULL) {
+ tty_buffer_free(tty, tty->buf.head);
+ tty->buf.head = thead;
}
- tty->buf.tail = NULL;
+ WARN_ON(tty->buf.head != tty->buf.tail);
+ tty->buf.head->read = tty->buf.head->commit;
}
/**
^ permalink raw reply related
* Re: [PATCH v2 1/1] staging: fwserial: Add TTY-over-Firewire serial driver
From: Stefan Richter @ 2012-11-27 23:58 UTC (permalink / raw)
To: Peter Hurley
Cc: devel, Greg Kroah-Hartman, linux-kernel, linux-serial,
linux1394-devel, Alan Cox
In-Reply-To: <1354041196.3284.121.camel@thor>
On Nov 27 Peter Hurley wrote:
> > > Currently, firewire-net sets an arbitrary address handler length of
> > > 4096. This works because the largest AR packet size the current
> > > firewire-ohci driver handles is 4096 (value of MAX_ASYNC_PAYLOAD) +
> > > header/trailer. Note that firewire-ohci does not limit card->max_receive
> > > to this value.
> > >
> > > So if the ohci driver changes to handle 8K+ AR packets and the hardware
> > > supports it, these address handler windows will be too small.
> >
> > While the IEEE 1394:2008 link layer specification (section 6) provides for
> > asynchronous packet payloads of up to 16384 bytes (table 6-4), the IEEE
> > 1394 beta mode port specification (section 13) only allows up to 4096
> > bytes (table 16-18). And alpha mode is of course limited to 2048 bytes.
> >
> > So, asynchronous packet payloads greater than 4096 bytes are out of scope
> > of the current revision of IEEE 1394.
>
> You should look at this 1394ta.org video
> http://www.youtube.com/watch?v=xVXNvXHNQTY of DAP Technologies S1600
> OHCI controllers running S1600 cameras using beta cables.
I don't know the details of their implementation, but I suppose they conform
with the 1394 beta mode port specification. Which in turn means that their
S1600 solution (and by extrapolation, their S3200 prototypes) comply with a
maximum asynchronous packet payload of 4096 bytes. Citing IEEE 1394-2008:
>>>
Table 16-18———Maximum payload size for Beta data packets
Data rate | Maximum asynchronous payload size | Maximum isochronous payload
| (bytes) | (bytes)
----------+-----------------------------------+----------------------------
S100 | 512 | 1024
S200 | 1024 | 2048
S400 | 2048 | 4096
S800 | 4096 | 8192
S1600 | 4096 | 16384
S3200 | 4096 | 32768
<<<
(Alpha mode payload limits are the same as the S100...S400 subset of beta mode.
In IEEE 1394b-2002, the table number is 16-3.)
You can of course define registers (or better termed: buffers) which are larger
than what can be atomically read or written, or atomically compared-swapped;
IOW which are larger than what can be accessed in a single transaction, if such
registers or buffers are useful. But if you particularly need a register which
is just large enough to accommodate the largest possible inbound block write
transaction which complies with IEEE 1394, and you don't know the peer's
capability and the speeds of all intermediary cable hops, then
fw_card.max_receive is the number that you need. Or you ignore the cards actual
capability and just allocate 4096 bytes.
OHCIs that you can buy offer fw_card.max_receive of 1024, or 2048, or 4096 bytes.
1024 bytes is the limit of many but not all 1394a S400 CardBus cards.
[Issues of transaction retries and possible loss at session termination to be
left to another reply at another time.]
--
Stefan Richter
-=====-===-- =-== ==-==
http://arcgraph.de/sr/
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel
^ permalink raw reply
* Re: [PULL REQUEST] Tweak to support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
From: Alan Cox @ 2012-11-27 23:00 UTC (permalink / raw)
To: Alexey Pelykh; +Cc: linux-serial
In-Reply-To: <CAOmKuSrQW1j_tmQNbXMO-GUH7zrUR0WR3K4rJNok=2LZmRKVYg@mail.gmail.com>
> In old driver that served UART devices (8250.c and serial_core.c) this
> divisor could have been configured by user-space program, but in
> omap_serial.c driver implementation this ability was not implemented
> (afaik, by design) thus disallowing proper usage of MODE16-compatible
> baudrates.
Yes in the ideal case the kernel should manage should things.
Looks fine to me from a tty perspective (style wise one might quibble
about baudAbsDiff but I really don;t care 8))
Acked-by: Alan Cox <alan@linux.intel.com>
^ permalink raw reply
* Fwd: [PULL REQUEST] Tweak to support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
From: Alexey Pelykh @ 2012-11-27 21:56 UTC (permalink / raw)
To: linux-serial
In-Reply-To: <CAOmKuSpjitfTeeXz6VKQbhe+iUFb8wYy4n3tAzbjr9g_GOAn4g@mail.gmail.com>
Hello everyone,
Original table in OMAP TRM named "UART Mode Baud Rates, Divisor
Values, and Error Rates" determines modes not for all common baud
rates. E.g. for 1000000 baud rate mode should be 16x, but according to
that table it's determined as 13x. According to current implementation
of mode
divisor selection, after requesting 1000000 baudrate from driver,
later one will configure chip to use MODE13 divisor. Assuming 48Mhz as
common UART clock speed, MODE13 divisor will effectively give 1230769
baudrate, what is quite far from desired 1000000 baudrate. While with
MODE16 divisor, chip will produce exact 1000000 baudrate.
In old driver that served UART devices (8250.c and serial_core.c) this
divisor could have been configured by user-space program, but in
omap_serial.c driver implementation this ability was not implemented
(afaik, by design) thus disallowing proper usage of MODE16-compatible
baudrates.
Best regards,
Alexey Pelykh
The following changes since commit 77b67063bb6bce6d475e910d3b886a606d0d91f7:
Linux 3.7-rc5 (2012-11-11 13:44:33 +0100)
are available in the git repository at:
git://github.com/alexey-pelykh/linux.git omap_serial_mode_fix
for you to fetch changes up to cf827bb4057fdcdaeac20b95b01c29c068109185:
Tweak to support 1Mbaud and similar baudrates that require Mode16
instead of Mode13 (2012-11-12 19:29:27 +0200)
----------------------------------------------------------------
Alexey Pelykh (1):
Tweak to support 1Mbaud and similar baudrates that require
Mode16 instead of Mode13
drivers/tty/serial/omap-serial.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6d3d26a..6d567dd 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -182,24 +182,42 @@ static void serial_omap_enable_wakeup(struct
uart_omap_port *up, bool enable)
}
/*
+ * serial_omap_baud_is_mode16 - check if baud rate is MODE16X
+ * @port: uart port info
+ * @baud: baudrate for which mode needs to be determined
+ *
+ * Returns true if baud rate is MODE16X and false if MODE13X
+ * Original table in OMAP TRM named "UART Mode Baud Rates, Divisor Values,
+ * and Error Rates" determines modes not for all common baud rates.
+ * E.g. for 1000000 baud rate mode must be 16x, but according to that
+ * table it's determined as 13x.
+ */
+static bool
+serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
+{
+ unsigned int n13 = port->uartclk / (13 * baud);
+ unsigned int n16 = port->uartclk / (16 * baud);
+ int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
+ int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
+ if(baudAbsDiff13 < 0)
+ baudAbsDiff13 = -baudAbsDiff13;
+ if(baudAbsDiff16 < 0)
+ baudAbsDiff16 = -baudAbsDiff16;
+
+ return (baudAbsDiff13 > baudAbsDiff16);
+}
+
+/*
* serial_omap_get_divisor - calculate divisor value
* @port: uart port info
* @baud: baudrate for which divisor needs to be calculated.
- *
- * We have written our own function to get the divisor so as to support
- * 13x mode. 3Mbps Baudrate as an different divisor.
- * Reference OMAP TRM Chapter 17:
- * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
- * referring to oversampling - divisor value
- * baudrate 460,800 to 3,686,400 all have divisor 13
- * except 3,000,000 which has divisor value 16
*/
static unsigned int
serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
{
unsigned int divisor;
- if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+ if (!serial_omap_baud_is_mode16(port, baud))
divisor = 13;
else
divisor = 16;
@@ -893,7 +911,7 @@ serial_omap_set_termios(struct uart_port *port,
struct ktermios *termios,
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, cval);
- if (baud > 230400 && baud != 3000000)
+ if (!serial_omap_baud_is_mode16(port, baud))
up->mdr1 = UART_OMAP_MDR1_13X_MODE;
else
up->mdr1 = UART_OMAP_MDR1_16X_MODE;
^ permalink raw reply related
* Re: [PULL REQUEST] Tweak to support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
From: Alan Cox @ 2012-11-27 21:46 UTC (permalink / raw)
To: Alexey Pelykh; +Cc: linux-serial
In-Reply-To: <CAOmKuSpjitfTeeXz6VKQbhe+iUFb8wYy4n3tAzbjr9g_GOAn4g@mail.gmail.com>
I am not going to go rummaging around in git repositories for patches.
Please post it to the list.
Alan
^ permalink raw reply
* Fwd: [PULL REQUEST] Tweak to support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
From: Alexey Pelykh @ 2012-11-27 21:35 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-serial
In-Reply-To: <CAOmKuSpRJhBibSDxTFCH157-XokhaFhvQ-gYxKZe+PfzokaBoA@mail.gmail.com>
Hello everyone,
Original table in OMAP TRM named "UART Mode Baud Rates, Divisor
Values, and Error Rates" determines modes not for all common baud
rates. E.g. for 1000000 baud rate mode should be 16x, but according to
that table it's determined as 13x. According to current implementation
of mode
divisor selection, after requesting 1000000 baudrate from driver,
later one will configure chip to use MODE13 divisor. Assuming 48Mhz as
common UART clock speed, MODE13 divisor will effectively give 1230769
baudrate, what is quite far from desired 1000000 baudrate. While with
MODE16 divisor, chip will produce exact 1000000 baudrate.
In old driver that served UART devices (8250.c and serial_core.c) this
divisor could have been configured by user-space program, but in
omap_serial.c driver implementation this ability was not implemented
(afaik, by design) thus disallowing proper usage of MODE16-compatible
baudrates.
Best regards,
Alexey Pelykh
The following changes since commit 77b67063bb6bce6d475e910d3b886a606d0d91f7:
Linux 3.7-rc5 (2012-11-11 13:44:33 +0100)
are available in the git repository at:
git://github.com/alexey-pelykh/linux.git omap_serial_mode_fix
for you to fetch changes up to cf827bb4057fdcdaeac20b95b01c29c068109185:
Tweak to support 1Mbaud and similar baudrates that require Mode16
instead of Mode13 (2012-11-12 19:29:27 +0200)
----------------------------------------------------------------
Alexey Pelykh (1):
Tweak to support 1Mbaud and similar baudrates that require
Mode16 instead of Mode13
drivers/tty/serial/omap-serial.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
^ permalink raw reply
* Re: [PATCH v4] tty: Add driver unthrottle in ioctl(...,TCFLSH,..).
From: Alan Cox @ 2012-11-27 19:32 UTC (permalink / raw)
To: Ilya Zykov; +Cc: Greg Kroah-Hartman, Alan Cox, linux-serial, linux-kernel
In-Reply-To: <50B50AA0.7070603@ilyx.ru>
> No, if only you will accept:
> [PATCH]tty: Incorrect use tty_ldisc_flush() in TTY drivers.
>
> It can be done another way, simple revert:
> 'tty: fix "IRQ45: nobody cared"'
> commit 7b292b4bf9a9d6098440d85616d6ca4c608b8304
NAK that revert - that swaps a minor glitch you've discovered that does
want fixing for a nasty bug.
^ permalink raw reply
* Re: [PATCH v4] tty: Add driver unthrottle in ioctl(...,TCFLSH,..).
From: Ilya Zykov @ 2012-11-27 18:46 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, linux-serial, linux-kernel, ilya
In-Reply-To: <20121127172406.GE24592@kroah.com>
On 27.11.2012 21:24, Greg Kroah-Hartman wrote:
> On Tue, Nov 27, 2012 at 10:14:33AM +0400, Ilya Zykov wrote:
>> Sorry. More correct.
>
> In what way? Should I wait for the 6th version? :)
>
> thanks,
>
> greg k-h
>
No, if only you will accept:
[PATCH]tty: Incorrect use tty_ldisc_flush() in TTY drivers.
It can be done another way, simple revert:
'tty: fix "IRQ45: nobody cared"'
commit 7b292b4bf9a9d6098440d85616d6ca4c608b8304
^ permalink raw reply
* Re: [PATCH v2 1/1] staging: fwserial: Add TTY-over-Firewire serial driver
From: Peter Hurley @ 2012-11-27 18:33 UTC (permalink / raw)
To: Stefan Richter
Cc: Greg Kroah-Hartman, Alan Cox, linux-kernel, devel,
linux1394-devel, linux-serial
In-Reply-To: <20121114022522.633a44d4@stein>
On Wed, 2012-11-14 at 02:25 +0100, Stefan Richter wrote:
> On Nov 13 Peter Hurley wrote:
> > On Tue, 2012-11-13 at 00:33 +0100, Stefan Richter wrote:
> > > On Nov 02 Peter Hurley wrote:
> > > > +2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci
> > > > + - otherwise how will this driver know the max size of address window to
> > > > + open for one packet write?
> > >
> > > Hmm, don't firewire-sbp2 and firewire-net deal with this very problem
> > > already on their own? Firewire-sbp2 tells the target what maximum payload
> > > the local node is ready to accept, and firewire-net figures out whether it
> > > needs to fragment the datagrams in unicast TX depending on the remote
> > > node's capabilities.
> >
> > I wasn't as clear as I should have been here. This is only about how big
> > to make the address handler window.
>
> Isn't fw_card.max_receive what you were looking for?
Yes, you're right, this is what I should do.
> But since the
> current firewire-core API requires you to allocate one handler address and
> size for all cards --- even for cards which will be hot-added later while
> your driver is already running ---, you should surely just allocate
> 4096 bytes; see below.
This driver uses a 2-stage negotiation scheme.
A small address window is allocated for all cards in the unit address
space. This address window is known to all peers because it is
advertised in the unit device config rom for all cards. The associated
handler handles requests for attach/detach from peers.
Then, when a local node is probed, the larger status+fifo address
windows are allocated (one address window for each tty port). Thus each
attached peer will get a dedicated address window.
The peer learns which status+fifo window it has been assigned
(corresponding to a particular tty port) while negotiating the attach.
Currently, the larger windows are allocated before knowledge of which
peer (or indeed any peer) might attempt to attach.
I will need to delay this allocation until during the attach
negotiation.
But if it's ok with you, maybe I can put this off for right now and just
note it in the TODO?
> > Just like firewire-net, this driver
> > communicates with remotes at S100 speeds (and packet sizes) to
> > query the largest packet size that the remote supports.
>
> (RFC 2734 additionally keeps things sane for itself by requiring all 2734
> compliant nodes to support at least max packet = 512 bytes.)
>
> Could it be easier to take this information from fw_device.max_speed and
> the max_rec in fw_device.config_rom? RFC 2734 was designed to work
> without a local node management layer which is capable to gather such
> information, but we have this information on Linux (at the time when
> core_device.c finished its node discovery).
I see your point and I hadn't considered that. That said, the
attach/detach negiotiation doesn't need optimizing, so I'm comfortable
leaving this as is.
> > Currently, firewire-net sets an arbitrary address handler length of
> > 4096. This works because the largest AR packet size the current
> > firewire-ohci driver handles is 4096 (value of MAX_ASYNC_PAYLOAD) +
> > header/trailer. Note that firewire-ohci does not limit card->max_receive
> > to this value.
> >
> > So if the ohci driver changes to handle 8K+ AR packets and the hardware
> > supports it, these address handler windows will be too small.
>
> While the IEEE 1394:2008 link layer specification (section 6) provides for
> asynchronous packet payloads of up to 16384 bytes (table 6-4), the IEEE
> 1394 beta mode port specification (section 13) only allows up to 4096
> bytes (table 16-18). And alpha mode is of course limited to 2048 bytes.
>
> So, asynchronous packet payloads greater than 4096 bytes are out of scope
> of the current revision of IEEE 1394.
You should look at this 1394ta.org video
http://www.youtube.com/watch?v=xVXNvXHNQTY of DAP Technologies S1600
OHCI controllers running S1600 cameras using beta cables. (I apologize
for the youtube link but that's where they hosted it :\)
> > > > +4. To avoid dropping rx data while still limiting the maximum buffering,
> > > > + the size of the AR context must be known. How to expose this to drivers?
> > >
> > > I don't see a requirement to know the local or remote node's size of AR
> > > DMA buffer. Rather, keep the traffic throttled such that too frequent
> > > ack-busy are avoided.
> [...]
> > I do need to implement retries but that will be of limited benefit to
> > this particular problem.
> >
> > Data is written from the remote as a posted write into the AR buffer.
> [...]
>
> Oh, I forgot about posted writes. However, you only lose data with posted
> writes if the OHCI somehow fails to access the host bus. Merely getting
> to the end of the DMA program before all of the PCI posting FIFO could be
> emptied is not a reason to drop data. See OHCI-1394 section 3.3 which
> speaks about the possibility to drop selfID/ IR/ AR-resp data if out of
> buffer, but not AR-req data.
>
> Well, maybe there are bad OHCI implementations which drop posted AR-req
> data...? I don't know.
When I refer to dropping rx data here, I mean this sequence for
receiving a posted write:
handle_ar_packet
fw_core_handle_request
handle_exclusive_region_request
handler->address_callback() => fwtty_port_handler(WRITE_BLOCK_REQUEST)
** tty buffer space is full so can't copy the data out of AR buffer **
That data will be dropped and need to be retransmitted. But see below.
> firewire-net uses posted writes too. But with IP-over-1394, delivery
> guarantee is handled further above if needed, not by the 1394
> encapsulation. firewire-sbp2 also uses posted writes, in two ways: With
> physical DMA to SCSI READ command data buffers, and for the SBP status
> FIFO. But physical DMA does not have a backing DMA program, and data loss
> during a status FIFO write would likely be covered by a SCSI transaction
> retry.
see below.
> [...]
> > Besides the inefficiency of re-sending data that has already been
> > received, retrying may not be possible. Consider when a console driver
> > (work-in-progress) writes to the remote using the same interface. It
> > could be one of the last things the remote does. And the most crucial
> > information is that last write.
>
> As mentioned, I have no idea how TTY works or is supposed to work. But
> even if the sending application is allowed to quit before its last
> outbound datagram was delivered, fwserial could still be made to deliver
> this last datagram at its own pace, with as many software retries as
> prudent.
Among the many uses for fast tty is to receive the output from a remote
console driver (where printk's go). The last printk coming from the
remote will be the most important as it may contain a vital clue as to
why the remote host died. (Note: most console drivers will busy-wait the
current cpu until the transmission completes or it times out).
That's why I'd like to only be forced to software retry if absolutely
necessary. To my mind, software retrying is partly avoidable if the
receiver can ensure enough tty buffer space is available at any given
time. To provide this guarantee, this driver reserves a buffer as large
as the AR-req buffer (initially I had wanted to simply use a watermark
within the existing tty buffers but that idea was a non-starter). This
way the receiver can throttle the remote but still receive all the data
the remote may already have sent that is already in the AR-req buffer.
Does that make sense?
Regards,
Peter Hurley
^ permalink raw reply
* Re: [PATCH v4] tty: Add driver unthrottle in ioctl(...,TCFLSH,..).
From: Greg Kroah-Hartman @ 2012-11-27 17:24 UTC (permalink / raw)
To: Ilya Zykov; +Cc: Alan Cox, linux-kernel, linux-serial
In-Reply-To: <50B45A49.2040104@ilyx.ru>
On Tue, Nov 27, 2012 at 10:14:33AM +0400, Ilya Zykov wrote:
> Sorry. More correct.
In what way? Should I wait for the 6th version? :)
thanks,
greg k-h
^ permalink raw reply
* [PATCH v4] tty: Add driver unthrottle in ioctl(...,TCFLSH,..).
From: Ilya Zykov @ 2012-11-27 6:14 UTC (permalink / raw)
To: Alan Cox; +Cc: Greg Kroah-Hartman, linux-kernel, linux-serial, ilya
Sorry. More correct.
Regression 'tty: fix "IRQ45: nobody cared"'
Regression commit 7b292b4bf9a9d6098440d85616d6ca4c608b8304
Function reset_buffer_flags() also invoked during the ioctl(...,TCFLSH,..).
At the time of request we can have full buffers and throttled driver too.
If we don't unthrottle driver, we can get forever throttled driver, because,
after request, we will have empty buffers and throttled driver and
there is no place to unthrottle driver.
It simple reproduce with "pty" pair then one side sleep on tty->write_wait,
and other side do ioctl(...,TCFLSH,..). Then there is no place to do writers wake up.
Signed-off-by: Ilya Zykov <ilya@ilyx.ru>
---
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 12b1fa0..4071a8f 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -1096,12 +1096,16 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
ld = tty_ldisc_ref_wait(tty);
switch (arg) {
case TCIFLUSH:
- if (ld && ld->ops->flush_buffer)
+ if (ld && ld->ops->flush_buffer) {
ld->ops->flush_buffer(tty);
+ tty_unthrottle(tty);
+ }
break;
case TCIOFLUSH:
- if (ld && ld->ops->flush_buffer)
+ if (ld && ld->ops->flush_buffer) {
ld->ops->flush_buffer(tty);
+ tty_unthrottle(tty);
+ }
/* fall through */
case TCOFLUSH:
tty_driver_flush_buffer(tty);
^ permalink raw reply related
* [PATCH] serial:ifx6x60:Delete SPI timer when shut down port
From: chao bi @ 2012-11-27 5:30 UTC (permalink / raw)
To: Alan Cox; +Cc: richardx.r.gorby, jun.d.chen, linux-serial, linux-kernel
When shut down SPI port, it's possible that MRDY has been asserted and a SPI
timer was activated waiting for SRDY assert, in the case, it needs to delete
this timer.
Signed-off-by: Chen Jun <jun.d.chen@intel.com>
Signed-off-by: channing <chao.bi@intel.com>
---
drivers/tty/serial/ifx6x60.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5b9bc19..f5e9666 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port)
container_of(port, struct ifx_spi_device, tty_port);
mrdy_set_low(ifx_dev);
+ del_timer(&ifx_dev->spi_timer);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
tasklet_kill(&ifx_dev->io_work_tasklet);
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCHv3] tty: Added a CONFIG_TTY option to allow removal of TTY
From: Joe Millenbach @ 2012-11-27 2:36 UTC (permalink / raw)
To: Jiri Slaby
Cc: Greg Kroah-Hartman, Alan Cox, linux-serial, linux-kernel,
Josh Triplett
In-Reply-To: <50B3FED8.7090100@gmail.com>
On Mon, Nov 26, 2012 at 3:44 PM, Jiri Slaby <jirislaby@gmail.com> wrote:
> On 11/27/2012 12:38 AM, Greg Kroah-Hartman wrote:
>> Can you rediff this once 3.8-rc1 is out and send it to me then?
>
> So if you are going to respin, please take care of the newly added
> drivers like drivers/staging/fwserial.
>
> thanks,
> --
> js
Will do on both counts (wait until 3.8-rc1, rebase, and search for TTY
uses in new drivers).
- Joe Millenbach
^ permalink raw reply
* [PATCH]tty: Incorrect use tty_ldisc_flush() in TTY drivers.
From: Ilya Zykov @ 2012-11-27 0:06 UTC (permalink / raw)
To: Alan Cox
Cc: Andrew McGregor, Greg Kroah-Hartman, linux-serial, linux-kernel,
ilya
Sorry. Correct patch format.
Related bug 'tty: fix "IRQ45: nobody cared"'
Related commit 7b292b4bf9a9d6098440d85616d6ca4c608b8304
Unfortunately, some drivers indirectly call ldisc's flush_buffer() function
in own callback function close(). In particularly, by the use of tty_ldisc_flush(),
before TTY LAYER calls ldisc's flush_buffer() in the right moment.
1. It disturb the logic of work ldisc's layer.
2. It is simple overhead because we call ldisc's flush_buffer() at least two times.
Please, tell me what do you think about this? Can I make the adjustment for other drivers?
Signed-off-by: Ilya Zykov <ilya@ilyx.ru>
---
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0fcfd98..d87f353 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1304,7 +1304,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
uart_shutdown(tty, state);
uart_flush_buffer(tty);
- tty_ldisc_flush(tty);
+ tty_buffer_flush(tty);
tty_port_tty_set(port, NULL);
spin_lock_irqsave(&port->lock, flags);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index d7bdd8d..8a02996 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -428,8 +428,8 @@ int tty_port_close_start(struct tty_port *port,
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
}
- /* Flush the ldisc buffering */
- tty_ldisc_flush(tty);
+ /* Flush the driver buffering */
+ tty_buffer_flush(tty);
/* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
hang up the line */
^ permalink raw reply related
* Re: [PATCH] serial:ifx6x60:Delete SPI timer when shut down port
From: Greg KH @ 2012-11-26 23:45 UTC (permalink / raw)
To: chao bi; +Cc: Alan Cox, richardx.r.gorby, jun.d.chen, linux-serial,
linux-kernel
In-Reply-To: <1353634413.22077.15.camel@bichao>
On Fri, Nov 23, 2012 at 09:33:33AM +0800, chao bi wrote:
>
> When shut down SPI port, it's possible that MRDY has been asserted and a SPI
> timer was activated waiting for SRDY assert, in the case, it needs to delete
> this timer.
This doesn't apply without fuzz, so I don't know what tree you are
working against here.
Please redo it against the latest version of the tty-next tree.
greg k-h
^ 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