All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] rework quirks for the "kt" serial port
@ 2012-04-09 18:21 Dan Williams
  2012-04-09 18:22 ` [PATCH v2 1/4] of_serial: add support for setup quirks Dan Williams
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Dan Williams @ 2012-04-09 18:21 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, linux-serial, alan

Changes since v1: http://marc.info/?l=linux-serial&m=133373702606784&w=2

1/ rebased series on 3.4-rc2 to fix up a collision in patch 2 and
   dropped the recently accepted patches out of this series

2/ introduced quirk infrastructure for open firmware serial devices and
   hooked it up for Tegra's serial quirk

3/ updated the changelog in patch 4 to show the problems with quirk
   handling during resume

4/ added Alan's ack to patches 2-4.  patch 1 is new.

Patch 1-3 are targetted at 3.5 (pending an ack from Tegra folks), patch
4 is a RFC as the KT resume case was already fixed by "Revert
"serial/8250_pci: init-quirk msi support for kt serial controller"

---

Dan Williams (3):
      of_serial: add support for setup quirks
      tegra, serial8250: add ->handle_break() uart_port op
      serial/8250_pci: fix suspend/resume vs init/exit quirks

Sudhakar Mamillapalli (1):
      serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI


 arch/arm/configs/tegra_defconfig      |    1 
 arch/arm/mach-tegra/board-harmony.c   |    4 +
 arch/arm/mach-tegra/board-paz00.c     |    5 ++
 arch/arm/mach-tegra/board-seaboard.c  |    4 +
 arch/arm/mach-tegra/board-trimslice.c |    4 +
 arch/arm/mach-tegra/devices.h         |    1 
 drivers/tty/serial/8250/8250.c        |   44 +++++----------
 drivers/tty/serial/8250/8250.h        |    2 +
 drivers/tty/serial/8250/8250_pci.c    |   45 ++++++++++++++++
 drivers/tty/serial/Kconfig            |    8 +++
 drivers/tty/serial/of_serial.c        |   95 ++++++++++++++++++++++++++-------
 include/linux/of_serial.h             |   17 ++++++
 include/linux/serial_8250.h           |    1 
 include/linux/serial_core.h           |    5 ++
 14 files changed, 183 insertions(+), 53 deletions(-)
 create mode 100644 include/linux/of_serial.h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/4] of_serial: add support for setup quirks
  2012-04-09 18:21 [PATCH v2 0/4] rework quirks for the "kt" serial port Dan Williams
@ 2012-04-09 18:22 ` Dan Williams
  2012-04-09 18:49   ` Arnd Bergmann
  2012-04-09 18:22 ` [PATCH v2 2/4] tegra, serial8250: add ->handle_break() uart_port op Dan Williams
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Dan Williams @ 2012-04-09 18:22 UTC (permalink / raw)
  To: gregkh
  Cc: Stephen Warren, Arnd Bergmann, linux-kernel, Grant Likely,
	linux-serial, Colin Cross, Olof Johansson, alan

Benign conversion of of_serial.c to offer the option of 'setup' quirks
similar to how 8250_pci.c houses the pci-serial-device quirks.

A setup quirk allows custom uart_port ops to specified in the
of_serial_info data fed to each serial of_device_id.

Tegra's 'break' quirk is the target consumer.

Cc: Colin Cross <ccross@android.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/tty/serial/of_serial.c |   68 ++++++++++++++++++++++++++++------------
 1 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index e8c9cee..4621cf9 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -22,13 +22,15 @@
 struct of_serial_info {
 	int type;
 	int line;
+	void (*setup)(struct uart_port *);
 };
 
 /*
  * Fill a struct uart_port for a given device node
  */
 static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
-					int type, struct uart_port *port)
+					      struct of_serial_info *info,
+					      struct uart_port *port)
 {
 	struct resource resource;
 	struct device_node *np = ofdev->dev.of_node;
@@ -78,12 +80,15 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 		}
 	}
 
-	port->type = type;
+	port->type = info->type;
 	port->uartclk = clk;
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
 		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
 	port->dev = &ofdev->dev;
 
+	if (info->setup)
+		info->setup(port);
+
 	return 0;
 }
 
@@ -96,7 +101,6 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 	const struct of_device_id *match;
 	struct of_serial_info *info;
 	struct uart_port port;
-	int port_type;
 	int ret;
 
 	match = of_match_device(of_platform_serial_table, &ofdev->dev);
@@ -106,16 +110,12 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
 		return -EBUSY;
 
-	info = kmalloc(sizeof(*info), GFP_KERNEL);
-	if (info == NULL)
-		return -ENOMEM;
-
-	port_type = (unsigned long)match->data;
-	ret = of_platform_serial_setup(ofdev, port_type, &port);
+	info = match->data;
+	ret = of_platform_serial_setup(ofdev, info, &port);
 	if (ret)
 		goto out;
 
-	switch (port_type) {
+	switch (info->type) {
 #ifdef CONFIG_SERIAL_8250
 	case PORT_8250 ... PORT_MAX_8250:
 		ret = serial8250_register_port(&port);
@@ -136,12 +136,10 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 	if (ret < 0)
 		goto out;
 
-	info->type = port_type;
 	info->line = ret;
 	dev_set_drvdata(&ofdev->dev, info);
 	return 0;
 out:
-	kfree(info);
 	irq_dispose_mapping(port.irq);
 	return ret;
 }
@@ -167,24 +165,52 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
 		/* need to add code for these */
 		break;
 	}
-	kfree(info);
 	return 0;
 }
 
 /*
+ * contiguous OF_ number space for serial port types so the
+ * __sinfo array does not have holes, and to allow cases of:
+ *  .type = 'common type', .setup = 'device specific quirk'
+ */
+enum {
+	OF_PORT_8250,
+	OF_PORT_16450,
+	OF_PORT_16550A,
+	OF_PORT_16550,
+	OF_PORT_16750,
+	OF_PORT_16850,
+	OF_PORT_TEGRA,
+	OF_PORT_NWPSERIAL,
+	OF_PORT_UNKNOWN,
+};
+
+static struct of_serial_info __refdata __sinfo[] = {
+	[OF_PORT_8250] = { .type = PORT_8250, },
+	[OF_PORT_16450] = { .type = PORT_16450, },
+	[OF_PORT_16550A] = { .type = PORT_16550A, },
+	[OF_PORT_16550] = { .type = PORT_16550, },
+	[OF_PORT_16750] = { .type = PORT_16750, },
+	[OF_PORT_16850] = { .type = PORT_16850, },
+	[OF_PORT_TEGRA] = { .type = PORT_TEGRA, },
+	[OF_PORT_NWPSERIAL] = { .type = PORT_NWPSERIAL, },
+	[OF_PORT_UNKNOWN] = { .type = PORT_UNKNOWN,  },
+};
+
+/*
  * A few common types, add more as needed.
  */
 static struct of_device_id __devinitdata of_platform_serial_table[] = {
-	{ .compatible = "ns8250",   .data = (void *)PORT_8250, },
-	{ .compatible = "ns16450",  .data = (void *)PORT_16450, },
-	{ .compatible = "ns16550a", .data = (void *)PORT_16550A, },
-	{ .compatible = "ns16550",  .data = (void *)PORT_16550, },
-	{ .compatible = "ns16750",  .data = (void *)PORT_16750, },
-	{ .compatible = "ns16850",  .data = (void *)PORT_16850, },
-	{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
+	{ .compatible = "ns8250",   .data = &__sinfo[OF_PORT_8250], },
+	{ .compatible = "ns16450",  .data = &__sinfo[OF_PORT_16450], },
+	{ .compatible = "ns16550a", .data = &__sinfo[OF_PORT_16550A], },
+	{ .compatible = "ns16550",  .data = &__sinfo[OF_PORT_16550], },
+	{ .compatible = "ns16750",  .data = &__sinfo[OF_PORT_16750], },
+	{ .compatible = "ns16850",  .data = &__sinfo[OF_PORT_16850], },
+	{ .compatible = "nvidia,tegra20-uart", .data = &__sinfo[OF_PORT_TEGRA], },
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
 	{ .compatible = "ibm,qpace-nwp-serial",
-		.data = (void *)PORT_NWPSERIAL, },
+		.data = &__sinfo[OF_PORT_NWPSERIAL], },
 #endif
 	{ .type = "serial",         .data = (void *)PORT_UNKNOWN, },
 	{ /* end of list */ },

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/4] tegra, serial8250: add ->handle_break() uart_port op
  2012-04-09 18:21 [PATCH v2 0/4] rework quirks for the "kt" serial port Dan Williams
  2012-04-09 18:22 ` [PATCH v2 1/4] of_serial: add support for setup quirks Dan Williams
@ 2012-04-09 18:22 ` Dan Williams
  2012-04-09 18:22 ` [PATCH v2 3/4] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI Dan Williams
  2012-04-09 18:22 ` [PATCH v2 4/4] serial/8250_pci: fix suspend/resume vs init/exit quirks Dan Williams
  3 siblings, 0 replies; 8+ messages in thread
From: Dan Williams @ 2012-04-09 18:22 UTC (permalink / raw)
  To: gregkh
  Cc: Sudhakar Mamillapalli, Stephen Warren, linux-kernel, Grant Likely,
	linux-serial, Colin Cross, Olof Johansson, Nhan H Mai, Alan Cox,
	Alan Cox

The "KT" serial port has another use case for a "received break" quirk,
so before adding another special case to the 8250 core take this
opportunity to push such quirks out of the core and into a uart_port op.

Stephen says:
"If the callback function is to no longer live in 8250.c itself,
 arch/arm/mach-tegra/devices.c isn't logically a good place to put it,
 and that file will be going away once we get rid of all the board files
 and move solely to device tree."

...so since 8250_pci.c houses all the quirks for pci serial devices this
quirk is similarly housed in of_serial.c.  Once the open firmware
conversion completes the infrastructure details (CONFIG_TEGRA_SERIAL,
include/linux/of_serial.h, and the export) can all be removed to make
this self contained to of_serial.c.

Cc: Nhan H Mai <nhan.h.mai@intel.com>
Cc: Colin Cross <ccross@android.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Sudhakar Mamillapalli <sudhakar@fb.com>
Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/arm/configs/tegra_defconfig      |    1 +
 arch/arm/mach-tegra/board-harmony.c   |    4 ++++
 arch/arm/mach-tegra/board-paz00.c     |    5 +++++
 arch/arm/mach-tegra/board-seaboard.c  |    4 ++++
 arch/arm/mach-tegra/board-trimslice.c |    4 ++++
 arch/arm/mach-tegra/devices.h         |    1 -
 drivers/tty/serial/8250/8250.c        |   34 +++------------------------------
 drivers/tty/serial/Kconfig            |    8 ++++++++
 drivers/tty/serial/of_serial.c        |   29 +++++++++++++++++++++++++++-
 include/linux/of_serial.h             |   17 +++++++++++++++++
 include/linux/serial_8250.h           |    1 +
 include/linux/serial_core.h           |    5 +++++
 12 files changed, 80 insertions(+), 33 deletions(-)
 create mode 100644 include/linux/of_serial.h

diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 351d670..de7288a 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -97,6 +97,7 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_TEGRA=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index c00aadb..b8ceac3 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/of_serial.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/pda_power.h>
@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		.irq		= INT_UARTD,
 		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
 		.type		= PORT_TEGRA,
+		.handle_break	= tegra_serial_handle_break,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -115,7 +117,9 @@ static void __init harmony_i2c_init(void)
 }
 
 static struct platform_device *harmony_devices[] __initdata = {
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA)
 	&debug_uart,
+#endif
 	&tegra_sdhci_device1,
 	&tegra_sdhci_device2,
 	&tegra_sdhci_device4,
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 330afdf..1113dab 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/of_serial.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio_keys.h>
@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		.irq		= INT_UARTA,
 		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
 		.type		= PORT_TEGRA,
+		.handle_break	= tegra_serial_handle_break,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		.irq		= INT_UARTC,
 		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
 		.type		= PORT_TEGRA,
+		.handle_break	= tegra_serial_handle_break,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -142,7 +145,9 @@ static struct platform_device gpio_keys_device = {
 };
 
 static struct platform_device *paz00_devices[] __initdata = {
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA)
 	&debug_uart,
+#endif
 	&tegra_sdhci_device4,
 	&tegra_sdhci_device1,
 	&wifi_rfkill_device,
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index d669847..59a30ab 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/of_serial.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/input.h>
@@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		/* Memory and IRQ filled in before registration */
 		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
 		.type		= PORT_TEGRA,
+		.handle_break	= tegra_serial_handle_break,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -145,7 +147,9 @@ static struct platform_device seaboard_audio_device = {
 };
 
 static struct platform_device *seaboard_devices[] __initdata = {
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA)
 	&debug_uart,
+#endif
 	&tegra_pmu_device,
 	&tegra_sdhci_device4,
 	&tegra_sdhci_device3,
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index cd52820..b156f55 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/of_serial.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
@@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		.irq		= INT_UARTA,
 		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
 		.type		= PORT_TEGRA,
+		.handle_break	= tegra_serial_handle_break,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -81,7 +83,9 @@ static struct platform_device trimslice_audio_device = {
 };
 
 static struct platform_device *trimslice_devices[] __initdata = {
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA)
 	&debug_uart,
+#endif
 	&tegra_sdhci_device1,
 	&tegra_sdhci_device4,
 	&tegra_i2s_device1,
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index ec45567..6e5f852 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -53,5 +53,4 @@ extern struct platform_device tegra_i2s_device1;
 extern struct platform_device tegra_i2s_device2;
 extern struct platform_device tegra_das_device;
 extern struct platform_device tegra_pcm_device;
-
 #endif
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 5c27f7e..cbd94c3 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1332,27 +1332,6 @@ static void serial8250_enable_ms(struct uart_port *port)
 }
 
 /*
- * Clear the Tegra rx fifo after a break
- *
- * FIXME: This needs to become a port specific callback once we have a
- * framework for this
- */
-static void clear_rx_fifo(struct uart_8250_port *up)
-{
-	unsigned int status, tmout = 10000;
-	do {
-		status = serial_in(up, UART_LSR);
-		if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
-			status = serial_in(up, UART_RX);
-		else
-			break;
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while (1);
-}
-
-/*
  * serial8250_rx_chars: processes according to the passed in LSR
  * value, and returns the remaining LSR bits not handled
  * by this Rx routine.
@@ -1386,20 +1365,10 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
 		up->lsr_saved_flags = 0;
 
 		if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
-			/*
-			 * For statistics only
-			 */
 			if (lsr & UART_LSR_BI) {
 				lsr &= ~(UART_LSR_FE | UART_LSR_PE);
 				port->icount.brk++;
 				/*
-				 * If tegra port then clear the rx fifo to
-				 * accept another break/character.
-				 */
-				if (port->type == PORT_TEGRA)
-					clear_rx_fifo(up);
-
-				/*
 				 * We do the SysRQ and SAK checking
 				 * here because otherwise the break
 				 * may get masked by ignore_status_mask
@@ -3037,6 +3006,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
 		port.serial_in		= p->serial_in;
 		port.serial_out		= p->serial_out;
 		port.handle_irq		= p->handle_irq;
+		port.handle_break	= p->handle_break;
 		port.set_termios	= p->set_termios;
 		port.pm			= p->pm;
 		port.dev		= &dev->dev;
@@ -3209,6 +3179,8 @@ int serial8250_register_port(struct uart_port *port)
 			uart->port.set_termios = port->set_termios;
 		if (port->pm)
 			uart->port.pm = port->pm;
+		if (port->handle_break)
+			uart->port.handle_break = port->handle_break;
 
 		if (serial8250_isa_config != NULL)
 			serial8250_isa_config(0, &uart->port,
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 665beb6..33fa6ec 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -380,6 +380,14 @@ config SERIAL_PXA_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+# FIXME remove this option when Tegra completes conversion to open firmware
+config SERIAL_TEGRA
+	bool "Tegra serial port support"
+	depends on SERIAL_OF_PLATFORM=y
+	help
+	  If you have a machine based on NVIDIA Tegra you can enable its
+	  onboard serial ports by enabling this option.
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARM && ARCH_SA1100
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 4621cf9..5a3b3f6 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -12,8 +12,10 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
@@ -168,6 +170,31 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA)
+void tegra_serial_handle_break(struct uart_port *p)
+{
+	unsigned int status, tmout = 10000;
+
+	do {
+		status = p->serial_in(p, UART_LSR);
+		if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+			status = p->serial_in(p, UART_RX);
+		else
+			break;
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while (1);
+}
+/* FIXME remove this export when tegra finishes conversion to open firmware */
+EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
+#endif
+
+static void tegra_setup_quirk(struct uart_port *port)
+{
+	port->handle_break = tegra_serial_handle_break;
+}
+
 /*
  * contiguous OF_ number space for serial port types so the
  * __sinfo array does not have holes, and to allow cases of:
@@ -192,7 +219,7 @@ static struct of_serial_info __refdata __sinfo[] = {
 	[OF_PORT_16550] = { .type = PORT_16550, },
 	[OF_PORT_16750] = { .type = PORT_16750, },
 	[OF_PORT_16850] = { .type = PORT_16850, },
-	[OF_PORT_TEGRA] = { .type = PORT_TEGRA, },
+	[OF_PORT_TEGRA] = { .type = PORT_TEGRA, .setup = tegra_setup_quirk, },
 	[OF_PORT_NWPSERIAL] = { .type = PORT_NWPSERIAL, },
 	[OF_PORT_UNKNOWN] = { .type = PORT_UNKNOWN,  },
 };
diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h
new file mode 100644
index 0000000..2035d96
--- /dev/null
+++ b/include/linux/of_serial.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_OF_SERIAL_H
+#define __LINUX_OF_SERIAL_H
+
+/*
+ * FIXME remove this file when tegra finishes conversion to open firmware,
+ * expectation is that all quirks will then be self-contained in
+ * drivers/tty/serial/of_serial.c.
+ */
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA)
+extern void tegra_serial_handle_break(struct uart_port *port);
+#else
+static inline void tegra_serial_handle_break(struct uart_port *port)
+{
+}
+#endif
+
+#endif /* __LINUX_OF_SERIAL */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 8f012f8..a522fd9 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -38,6 +38,7 @@ struct plat_serial8250_port {
 	int		(*handle_irq)(struct uart_port *);
 	void		(*pm)(struct uart_port *, unsigned int state,
 			      unsigned old);
+	void		(*handle_break)(struct uart_port *);
 };
 
 /*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 2db407a..65db992 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -310,6 +310,7 @@ struct uart_port {
 	int			(*handle_irq)(struct uart_port *);
 	void			(*pm)(struct uart_port *, unsigned int state,
 				      unsigned int old);
+	void			(*handle_break)(struct uart_port *);
 	unsigned int		irq;			/* irq number */
 	unsigned long		irqflags;		/* irq flags  */
 	unsigned int		uartclk;		/* base uart clock */
@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
 static inline int uart_handle_break(struct uart_port *port)
 {
 	struct uart_state *state = port->state;
+
+	if (port->handle_break)
+		port->handle_break(port);
+
 #ifdef SUPPORT_SYSRQ
 	if (port->cons && port->cons->index == port->line) {
 		if (!port->sysrq) {

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/4] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI
  2012-04-09 18:21 [PATCH v2 0/4] rework quirks for the "kt" serial port Dan Williams
  2012-04-09 18:22 ` [PATCH v2 1/4] of_serial: add support for setup quirks Dan Williams
  2012-04-09 18:22 ` [PATCH v2 2/4] tegra, serial8250: add ->handle_break() uart_port op Dan Williams
@ 2012-04-09 18:22 ` Dan Williams
  2012-04-09 18:22 ` [PATCH v2 4/4] serial/8250_pci: fix suspend/resume vs init/exit quirks Dan Williams
  3 siblings, 0 replies; 8+ messages in thread
From: Dan Williams @ 2012-04-09 18:22 UTC (permalink / raw)
  To: gregkh
  Cc: Sudhakar Mamillapalli, Nhan H Mai, linux-kernel, linux-serial,
	Alan Cox

From: Sudhakar Mamillapalli <sudhakar@fb.com>

When using Serial Over Lan (SOL) over the virtual serial port in a Intel
management engine (ME) device, on device reset the serial FIFOs need to
be cleared to keep the FIFO indexes in-sync between the host and the
engine.

On a reset the serial device assertes BI, so using that as a cue FIFOs
are cleared.  So for this purpose a new handle_break callback has been
added.  One other problem is that the serial registers might temporarily
go to 0 on reset of this device.  So instead of using the IER register
read, if 0 returned use the ier value in uart_8250_port. This is hidden
under a custom serial_in.

Cc: Nhan H Mai <nhan.h.mai@intel.com>
Signed-off-by: Sudhakar Mamillapalli <sudhakar@fb.com>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/tty/serial/8250/8250.c     |   10 +++++++++
 drivers/tty/serial/8250/8250.h     |    2 ++
 drivers/tty/serial/8250/8250_pci.c |   39 ++++++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index cbd94c3..182efcc 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -568,6 +568,16 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
 	}
 }
 
+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
+{
+	unsigned char fcr;
+
+	serial8250_clear_fifos(p);
+	fcr = uart_config[p->port.type].fcr;
+	serial_out(p, UART_FCR, fcr);
+}
+EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+
 /*
  * IER sleep support.  UARTs which have EFRs need the "extended
  * capability" bit enabled.  Note that on XR16C850s, we need to
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 2868a1d..c9d0ebe 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -96,6 +96,8 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
 	up->port.serial_out(&up->port, offset, value);
 }
 
+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
+
 #if defined(__alpha__) && !defined(CONFIG_PCI)
 /*
  * Digital did something really horribly wrong with the OUT1 and OUT2
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 858dca8..024551a 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
+#include <linux/serial_reg.h>
 #include <linux/serial_core.h>
 #include <linux/8250_pci.h>
 #include <linux/bitops.h>
@@ -1092,11 +1093,49 @@ static int skip_tx_en_setup(struct serial_private *priv,
 	return pci_default_setup(priv, board, port, idx);
 }
 
+static void kt_handle_break(struct uart_port *p)
+{
+	struct uart_8250_port *up =
+		container_of(p, struct uart_8250_port, port);
+	/*
+	 * On receipt of a BI, serial device in Intel ME (Intel
+	 * management engine) needs to have its fifos cleared for sane
+	 * SOL (Serial Over Lan) output.
+	 */
+	serial8250_clear_and_reinit_fifos(up);
+}
+
+static unsigned int kt_serial_in(struct uart_port *p, int offset)
+{
+	struct uart_8250_port *up =
+		container_of(p, struct uart_8250_port, port);
+	unsigned int val;
+
+	/*
+	 * When the Intel ME (management engine) gets reset its serial
+	 * port registers could return 0 momentarily.  Functions like
+	 * serial8250_console_write, read and save the IER, perform
+	 * some operation and then restore it.  In order to avoid
+	 * setting IER register inadvertently to 0, if the value read
+	 * is 0, double check with ier value in uart_8250_port and use
+	 * that instead.  up->ier should be the same value as what is
+	 * currently configured.
+	 */
+	val = inb(p->iobase + offset);
+	if (offset == UART_IER) {
+		if (val == 0)
+			val = up->ier;
+	}
+	return val;
+}
+
 static int kt_serial_setup(struct serial_private *priv,
 			   const struct pciserial_board *board,
 			   struct uart_port *port, int idx)
 {
 	port->flags |= UPF_BUG_THRE;
+	port->serial_in = kt_serial_in;
+	port->handle_break = kt_handle_break;
 	return skip_tx_en_setup(priv, board, port, idx);
 }
 

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 4/4] serial/8250_pci: fix suspend/resume vs init/exit quirks
  2012-04-09 18:21 [PATCH v2 0/4] rework quirks for the "kt" serial port Dan Williams
                   ` (2 preceding siblings ...)
  2012-04-09 18:22 ` [PATCH v2 3/4] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI Dan Williams
@ 2012-04-09 18:22 ` Dan Williams
  3 siblings, 0 replies; 8+ messages in thread
From: Dan Williams @ 2012-04-09 18:22 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, linux-serial, Alan Cox

Commit e86ff4a6 "serial/8250_pci: init-quirk msi support for kt serial
controller" introduced a regression in suspend/resume by causing msi's
to be enabled twice without an intervening disable.

00:16.3 Serial controller: Intel Corporation Patsburg KT Controller (rev 05) (prog-if 02 [16550])
       Subsystem: Intel Corporation Device 7270
       Flags: bus master, 66MHz, fast devsel, latency 0, IRQ 72
       I/O ports at 4080 [size=8]
       Memory at d1c30000 (32-bit, non-prefetchable) [size=4K]
       Capabilities: [c8] Power Management version 3
       Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
       Kernel driver in use: serial

[  365.250523] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:16.3/msi_irqs'
[  365.250525] Modules linked in: nls_utf8 ipv6 uinput sg iTCO_wdt
  iTCO_vendor_support ioatdma dca i2c_i801 i2c_core wmi sd_mod ahci libahci isci
  libsas libata scsi_transport_sas [last unloaded: scsi_wait_scan]
[  365.250540] Pid: 9030, comm: kworker/u:1 Tainted: G        W    3.3.0-isci-3.0.213+ #1
[  365.250542] Call Trace:
[  365.250545]  [<ffffffff8115e955>] ? sysfs_add_one+0x99/0xad
[  365.250548]  [<ffffffff8102db8b>] warn_slowpath_common+0x85/0x9e
[  365.250551]  [<ffffffff8102dc96>] warn_slowpath_fmt+0x6e/0x70
[  365.250555]  [<ffffffff8115e8fa>] ? sysfs_add_one+0x3e/0xad
[  365.250558]  [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
[  365.250561]  [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
[  365.250564]  [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
[  365.250567]  [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
[  365.250570]  [<ffffffff8115e955>] sysfs_add_one+0x99/0xad
[  365.250573]  [<ffffffff8115f031>] create_dir+0x72/0xa5
[  365.250577]  [<ffffffff8115f194>] sysfs_create_dir+0xa2/0xbe
[  365.250581]  [<ffffffff81262463>] kobject_add_internal+0x126/0x1f8
[  365.250585]  [<ffffffff8126255b>] kset_register+0x26/0x3f
[  365.250588]  [<ffffffff8126275a>] kset_create_and_add+0x62/0x7c
[  365.250592]  [<ffffffff81293619>] populate_msi_sysfs+0x34/0x103
[  365.250595]  [<ffffffff81293e1c>] pci_enable_msi_block+0x1b3/0x216
[  365.250599]  [<ffffffff81303f7c>] try_enable_msi+0x13/0x17
[  365.250603]  [<ffffffff81303fb3>] pciserial_resume_ports+0x21/0x42
[  365.250607]  [<ffffffff81304041>] pciserial_resume_one+0x50/0x57
[  365.250610]  [<ffffffff81283e1a>] pci_legacy_resume+0x38/0x47
[  365.250613]  [<ffffffff81283e7d>] pci_pm_restore+0x54/0x87
[  365.250616]  [<ffffffff81283e29>] ? pci_legacy_resume+0x47/0x47
[  365.250619]  [<ffffffff8131e9e8>] dpm_run_callback+0x48/0x7b
[  365.250623]  [<ffffffff8131f39a>] device_resume+0x342/0x394
[  365.250626]  [<ffffffff8131f5b7>] async_resume+0x21/0x49

That patch has since been reverted, but by inspection it seems that
pciserial_suspend_ports() should be invoking .exit() quirks to release
resources acquired during .init().

Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/tty/serial/8250/8250_pci.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 024551a..24ea98c 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -2814,6 +2814,12 @@ void pciserial_suspend_ports(struct serial_private *priv)
 	for (i = 0; i < priv->nr; i++)
 		if (priv->line[i] >= 0)
 			serial8250_suspend_port(priv->line[i]);
+
+	/*
+	 * Ensure that every init quirk is properly torn down
+	 */
+	if (priv->quirk->exit)
+		priv->quirk->exit(priv->dev);
 }
 EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
 


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/4] of_serial: add support for setup quirks
  2012-04-09 18:22 ` [PATCH v2 1/4] of_serial: add support for setup quirks Dan Williams
@ 2012-04-09 18:49   ` Arnd Bergmann
  2012-04-09 19:15       ` Williams, Dan J
  0 siblings, 1 reply; 8+ messages in thread
From: Arnd Bergmann @ 2012-04-09 18:49 UTC (permalink / raw)
  To: Dan Williams
  Cc: gregkh, Stephen Warren, linux-kernel, Grant Likely, linux-serial,
	Colin Cross, Olof Johansson, alan

On Monday 09 April 2012, Dan Williams wrote:
> Benign conversion of of_serial.c to offer the option of 'setup' quirks
> similar to how 8250_pci.c houses the pci-serial-device quirks.
> 
> A setup quirk allows custom uart_port ops to specified in the
> of_serial_info data fed to each serial of_device_id.
> 
> Tegra's 'break' quirk is the target consumer.
> 
> Cc: Colin Cross <ccross@android.com>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Stephen Warren <swarren@nvidia.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/tty/serial/of_serial.c |   68 ++++++++++++++++++++++++++++------------
>  1 files changed, 47 insertions(+), 21 deletions(-)

I don't think this is a good idea. Aside from the bug that you introduce
(you can no longer have multiple ports of the same type because of overwrite
the static info->line number), it seems an unnecessary complication.
Either just add the quirk to the of_serial file based on the compatible value,
or do a trivial new driver that has a subset of the existing one you need,
plus the quirk.

	Arnd 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/4] of_serial: add support for setup quirks
  2012-04-09 18:49   ` Arnd Bergmann
@ 2012-04-09 19:15       ` Williams, Dan J
  0 siblings, 0 replies; 8+ messages in thread
From: Williams, Dan J @ 2012-04-09 19:15 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: gregkh, Stephen Warren, linux-kernel, Grant Likely, linux-serial,
	Colin Cross, Olof Johansson, alan

On Mon, Apr 9, 2012 at 11:49 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 09 April 2012, Dan Williams wrote:
>> Benign conversion of of_serial.c to offer the option of 'setup' quirks
>> similar to how 8250_pci.c houses the pci-serial-device quirks.
>>
>> A setup quirk allows custom uart_port ops to specified in the
>> of_serial_info data fed to each serial of_device_id.
>>
>> Tegra's 'break' quirk is the target consumer.
>>
>> Cc: Colin Cross <ccross@android.com>
>> Cc: Olof Johansson <olof@lixom.net>
>> Cc: Stephen Warren <swarren@nvidia.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>> ---
>>  drivers/tty/serial/of_serial.c |   68 ++++++++++++++++++++++++++++------------
>>  1 files changed, 47 insertions(+), 21 deletions(-)
>
> I don't think this is a good idea. Aside from the bug that you introduce
> (you can no longer have multiple ports of the same type because of overwrite
> the static info->line number),

ah, yes, good catch.

> it seems an unnecessary complication.
> Either just add the quirk to the of_serial file based on the compatible value,
> or do a trivial new driver that has a subset of the existing one you need,
> plus the quirk.

ok.

The open question was where to house tegra_serial_handle_break, I'd
just as soon keep it all in of_serial.c and maintain the temporary
exports for use in the to-be-removed board files in
arch/arm/mach-tegra.

--
Dan
--
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	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/4] of_serial: add support for setup quirks
@ 2012-04-09 19:15       ` Williams, Dan J
  0 siblings, 0 replies; 8+ messages in thread
From: Williams, Dan J @ 2012-04-09 19:15 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: gregkh, Stephen Warren, linux-kernel, Grant Likely, linux-serial,
	Colin Cross, Olof Johansson, alan

On Mon, Apr 9, 2012 at 11:49 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 09 April 2012, Dan Williams wrote:
>> Benign conversion of of_serial.c to offer the option of 'setup' quirks
>> similar to how 8250_pci.c houses the pci-serial-device quirks.
>>
>> A setup quirk allows custom uart_port ops to specified in the
>> of_serial_info data fed to each serial of_device_id.
>>
>> Tegra's 'break' quirk is the target consumer.
>>
>> Cc: Colin Cross <ccross@android.com>
>> Cc: Olof Johansson <olof@lixom.net>
>> Cc: Stephen Warren <swarren@nvidia.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>> ---
>>  drivers/tty/serial/of_serial.c |   68 ++++++++++++++++++++++++++++------------
>>  1 files changed, 47 insertions(+), 21 deletions(-)
>
> I don't think this is a good idea. Aside from the bug that you introduce
> (you can no longer have multiple ports of the same type because of overwrite
> the static info->line number),

ah, yes, good catch.

> it seems an unnecessary complication.
> Either just add the quirk to the of_serial file based on the compatible value,
> or do a trivial new driver that has a subset of the existing one you need,
> plus the quirk.

ok.

The open question was where to house tegra_serial_handle_break, I'd
just as soon keep it all in of_serial.c and maintain the temporary
exports for use in the to-be-removed board files in
arch/arm/mach-tegra.

--
Dan

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-04-09 19:15 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-09 18:21 [PATCH v2 0/4] rework quirks for the "kt" serial port Dan Williams
2012-04-09 18:22 ` [PATCH v2 1/4] of_serial: add support for setup quirks Dan Williams
2012-04-09 18:49   ` Arnd Bergmann
2012-04-09 19:15     ` Williams, Dan J
2012-04-09 19:15       ` Williams, Dan J
2012-04-09 18:22 ` [PATCH v2 2/4] tegra, serial8250: add ->handle_break() uart_port op Dan Williams
2012-04-09 18:22 ` [PATCH v2 3/4] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI Dan Williams
2012-04-09 18:22 ` [PATCH v2 4/4] serial/8250_pci: fix suspend/resume vs init/exit quirks Dan Williams

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.