From: Stephen Hurd <shurd@xxxxxxxxxxxx> Add support for the UART device present in Broadcom TruManage capable NetXtreme chips (ie: 5761m 5762, and 5725). This implementation has a hidden transmit FIFO, so running in single-byte interrupt mode results in too many interrupts. The UART_CAP_HFIFO capability was added to track this. It continues to reload the THR as long as the THRE and TSRE bits are set in the LSR up to a specified limit (1024 is used here). Signed-off-by: Stephen Hurd <shurd@xxxxxxxxxxxx> --- Patch against linux-2.7 from ftp.kernel.org downloaded Dec-11-2012. I don't know anybody here off hand who does Linux work nor am I in a position to configure the Exchange server. If this still isn't acceptable, I guess I could try emailing this patch around internally and hope it lands with someone has the appropriate magic available. -- Stephen Hurd
diff -uprN linux-3.7.orig/drivers/tty/serial/8250/8250.c linux-3.7/drivers/tty/serial/8250/8250.c --- linux-3.7.orig/drivers/tty/serial/8250/8250.c 2012-12-10 19:30:57.000000000 -0800 +++ linux-3.7/drivers/tty/serial/8250/8250.c 2012-12-11 15:56:40.686343959 -0800 @@ -290,6 +290,12 @@ static const struct serial8250_config ua UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, .flags = UART_CAP_FIFO, }, + [PORT_BRCM_TRUMANAGE] = { + .name = "TruManage", + .fifo_size = 1, + .tx_loadsz = 1024, + .flags = UART_CAP_HFIFO, + }, [PORT_8250_CIR] = { .name = "CIR port" } @@ -1441,6 +1447,11 @@ void serial8250_tx_chars(struct uart_825 port->icount.tx++; if (uart_circ_empty(xmit)) break; + if (up->capabilities & UART_CAP_HFIFO) { + if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) + != BOTH_EMPTY) + break; + } } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) diff -uprN linux-3.7.orig/drivers/tty/serial/8250/8250.h linux-3.7/drivers/tty/serial/8250/8250.h --- linux-3.7.orig/drivers/tty/serial/8250/8250.h 2012-12-10 19:30:57.000000000 -0800 +++ linux-3.7/drivers/tty/serial/8250/8250.h 2012-12-11 14:57:48.641613676 -0800 @@ -40,6 +40,7 @@ struct serial8250_config { #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ +#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ diff -uprN linux-3.7.orig/drivers/tty/serial/8250/8250_pci.c linux-3.7/drivers/tty/serial/8250/8250_pci.c --- linux-3.7.orig/drivers/tty/serial/8250/8250_pci.c 2012-12-10 19:30:57.000000000 -0800 +++ linux-3.7/drivers/tty/serial/8250/8250_pci.c 2012-12-11 15:58:10.958340077 -0800 @@ -1085,6 +1085,17 @@ pci_omegapci_setup(struct serial_private return setup_port(priv, port, 2, idx * 8, 0); } +static int +pci_brcm_trumanage_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_port *port, int idx) +{ + int ret = pci_default_setup(priv, board, port, idx); + port->type = PORT_BRCM_TRUMANAGE; + port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + return ret; +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1213,6 +1224,7 @@ pci_wch_ch353_setup(struct serial_privat #define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 #define PCI_VENDOR_ID_ASIX 0x9710 +#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1788,6 +1800,17 @@ static struct pci_serial_quirk pci_seria .setup = pci_asix_setup, }, /* + * Broadcom TruManage (NetXtreme) + */ + { + .vendor = PCI_VENDOR_ID_BROADCOM, + .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_brcm_trumanage_setup, + }, + + /* * Default "match everything" terminator entry */ { @@ -1975,6 +1998,7 @@ enum pci_board_num_t { pbn_ce4100_1_115200, pbn_omegapci, pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, }; /* @@ -2674,6 +2698,12 @@ static struct pciserial_board pci_boards .num_ports = 2, .base_baud = 115200, }, + [pbn_brcm_trumanage] = { + .flags = FL_BASE0, + .num_ports = 1, + .reg_shift = 2, + .base_baud = 115200, + }, }; static const struct pci_device_id blacklist[] = { @@ -4238,6 +4268,13 @@ static struct pci_device_id serial_pci_t pbn_omegapci }, /* + * Broadcom TruManage + */ + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_brcm_trumanage }, + + /* * AgeStar as-prs2-009 */ { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, diff -uprN linux-3.7.orig/include/uapi/linux/serial_core.h linux-3.7/include/uapi/linux/serial_core.h --- linux-3.7.orig/include/uapi/linux/serial_core.h 2012-12-10 19:30:57.000000000 -0800 +++ linux-3.7/include/uapi/linux/serial_core.h 2012-12-11 15:00:07.005618440 -0800 @@ -49,7 +49,8 @@ #define PORT_XR17D15X 21 /* Exar XR17D15x UART */ #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ #define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */ -#define PORT_MAX_8250 23 /* max port ID */ +#define PORT_BRCM_TRUMANAGE 24 +#define PORT_MAX_8250 24 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed