| From koba@kmckk.co.jp Wed Oct 3 04:26:23 2012 |
| From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> |
| Date: Wed, 3 Oct 2012 20:22:54 +0900 |
| Subject: [PATCH 02/26] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI |
| To: greg@kroah.com |
| Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Sudhakar Mamillapalli <sudhakar@fb.com>, Nhan H Mai <nhan.h.mai@intel.com>, Dan Williams <dan.j.williams@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> |
| Message-ID: <1349263398-13152-3-git-send-email-koba@kmckk.co.jp> |
| |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit 0ad372b962d109323d18ac2aa118b2ad100eb8dd) |
| |
| Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> |
| --- |
| 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(+) |
| |
| diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c |
| index aed9363..c9ac4ea 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 3614973..5a4de9a 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); |
| } |
| |
| -- |
| 1.7.9.5 |
| |