From 909bc7741bef0bda57489884cf2e914c3072aca9 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 31 Mar 2011 15:35:31 -0300 Subject: vt: remove uneeded retval check before tty->ops->open inside tty_open The current check is uneeded, since !retval will always returns true, as retval returned from tty_add_file is checked earlier and tty_open exits if it's not zero. Acked-by: Alan Cox Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d7d50b48287..188632e4734 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1902,12 +1902,10 @@ got_driver: #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "opening %s...", tty->name); #endif - if (!retval) { - if (tty->ops->open) - retval = tty->ops->open(tty, filp); - else - retval = -ENODEV; - } + if (tty->ops->open) + retval = tty->ops->open(tty, filp); + else + retval = -ENODEV; filp->f_flags = saved_flags; if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && -- cgit v1.2.2 From 60680f97d7412b471d21ef42d4860657a0f9f2ed Mon Sep 17 00:00:00 2001 From: Arthur Taylor Date: Thu, 17 Mar 2011 01:47:32 -0700 Subject: vt: Add K_OFF return value to vt_ioctl KDGKBMODE After adding support for K_OFF in KDSKBMODE, it was forgotten to add support for returning it in KDGKBMODE. Signed-off-by: Arthur Taylor Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 937d1721998..e71477a860c 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -701,6 +701,7 @@ int vt_ioctl(struct tty_struct *tty, uival = ((kbd->kbdmode == VC_RAW) ? K_RAW : (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : + (kbd->kbdmode == VC_OFF) ? K_OFF : K_XLATE); goto setint; -- cgit v1.2.2 From 6da9e95f7381fa27bc9c66c9840b11adde778618 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 7 Apr 2011 16:13:01 -0700 Subject: drivers/tty/vt/vt_ioctl.c: repair insane ?: expression Cc: Arthur Taylor Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index e71477a860c..01ccd9e93b7 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -698,11 +698,23 @@ int vt_ioctl(struct tty_struct *tty, break; case KDGKBMODE: - uival = ((kbd->kbdmode == VC_RAW) ? K_RAW : - (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : - (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : - (kbd->kbdmode == VC_OFF) ? K_OFF : - K_XLATE); + switch (kbd->kbdmode) { + case VC_RAW: + uival = K_RAW; + break; + case VC_MEDIUMRAW: + uival = K_MEDIUMRAW; + break; + case VC_UNICODE: + uival = K_UNICODE; + break; + case VC_OFF: + uival = K_OFF; + break; + default: + uival = K_XLATE; + break; + } goto setint; /* this could be folded into KDSKBMODE, but for compatibility -- cgit v1.2.2 From 52ea383aba4d86d213622b2d4a94b01b4439fe11 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 09:49:54 +0100 Subject: tty: VT, remove unused variable drivers/tty/vt/vt_ioctl.c:1525:2: warning: Value stored to 'kbd' is never read kbd = kbd_table + console; ^ ~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 01ccd9e93b7..54851544d7c 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -1512,7 +1512,6 @@ long vt_compat_ioctl(struct tty_struct *tty, { struct vc_data *vc = tty->driver_data; struct console_font_op op; /* used in multiple places here */ - struct kbd_struct *kbd; unsigned int console; void __user *up = (void __user *)arg; int perm; @@ -1535,7 +1534,6 @@ long vt_compat_ioctl(struct tty_struct *tty, if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) perm = 1; - kbd = kbd_table + console; switch (cmd) { /* * these need special handlers for incompatible data structures -- cgit v1.2.2 From 4fd53ef5c97ef7ce909c18bf7fb8b5cdd72b08c1 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 09:49:55 +0100 Subject: TTY: serial_core, remove unused variable drivers/tty/serial/serial_core.c:1980:2: warning: Value stored to 'tty' is never read tty = port->tty; ^ ~~~~~~~~~ Signed-off-by: Jiri Slaby Acked-by: Govindraj.R Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 733fe8e73f0..d6e72403449 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1972,13 +1972,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) struct tty_port *port = &state->port; struct device *tty_dev; struct uart_match match = {uport, drv}; - struct tty_struct *tty; mutex_lock(&port->mutex); - /* Must be inside the mutex lock until we convert to tty_port */ - tty = port->tty; - tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (device_may_wakeup(tty_dev)) { if (!enable_irq_wake(uport->irq)) -- cgit v1.2.2 From 0e7f4194a0ef70c1d0d40152fa480a63719f35d5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 09:49:56 +0100 Subject: Char: cyclades, fix unused variable drivers/tty/cyclades.c:1454:2: warning: Value stored to 'channel' is never read channel = info->line - card->first_line; ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fix it by moving it to the appropriate debug section where it is used. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/cyclades.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index c99728f0cd9..e6f20d24e26 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1445,13 +1445,11 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) { struct cyclades_card *card; unsigned long flags; - int channel; if (!(info->port.flags & ASYNC_INITIALIZED)) return; card = info->card; - channel = info->line - card->first_line; if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); @@ -1476,6 +1474,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) spin_unlock_irqrestore(&card->card_lock, flags); } else { #ifdef CY_DEBUG_OPEN + int channel = info->line - card->first_line; printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " "base_addr %p\n", card, channel, card->base_addr); #endif -- cgit v1.2.2 From f2ee4ae87d7781ddb5bf8da25591b9b79966f8ea Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 09:49:57 +0100 Subject: TTY: VT, remove unused variables drivers/tty/vt/vt.c:892:2: warning: Value stored to 'old_screen_size' is never read old_screen_size = vc->vc_screenbuf_size; ^ ~~~~~~~~~~~~~~~~~~~~~ drivers/tty/vt/vt.c:890:2: warning: Value stored to 'old_cols' is never read old_cols = vc->vc_cols; ^ ~~~~~~~~~~~ Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4bea1efaec9..f287dca0d9d 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -858,7 +858,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned long end; - unsigned int old_cols, old_rows, old_row_size, old_screen_size; + unsigned int old_rows, old_row_size; unsigned int new_cols, new_rows, new_row_size, new_screen_size; unsigned int user; unsigned short *newscreen; @@ -887,9 +887,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, return -ENOMEM; old_rows = vc->vc_rows; - old_cols = vc->vc_cols; old_row_size = vc->vc_size_row; - old_screen_size = vc->vc_screenbuf_size; err = resize_screen(vc, new_cols, new_rows, user); if (err) { -- cgit v1.2.2 From 9d86f71b599a3f59bc9fe7eabf6c84c8c3a37fe0 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 09:49:59 +0100 Subject: Char: moxa, remove unused variables drivers/tty/moxa.c:1287:2: warning: Value stored to 'port' is never read port = tty->index; ^ ~~~~~~~~~~ drivers/tty/moxa.c:1763:2: warning: Value stored to 'cflag' is never read cflag = termio->c_cflag; /* termio->c_cflag */ ^ ~~~~~~~~~~~~~~~ Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/moxa.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 35b0c38590e..ffdaab39314 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1281,10 +1281,8 @@ static int moxa_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct moxa_port *ch; - int port; int dtr, rts; - port = tty->index; mutex_lock(&moxa_openlock); ch = tty->driver_data; if (!ch) { @@ -1756,11 +1754,9 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, speed_t baud) { void __iomem *ofsAddr; - tcflag_t cflag; tcflag_t mode = 0; ofsAddr = port->tableAddr; - cflag = termio->c_cflag; /* termio->c_cflag */ mode = termio->c_cflag & CSIZE; if (mode == CS5) -- cgit v1.2.2 From d65c57f4ece4c31380eef9975a04840df7b260cc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 09:50:00 +0100 Subject: TTY: rocket, remove unused variables drivers/tty/rocket.c:1393:2: warning: Value stored to 'cp' is never read cp = &info->channel; ^ ~~~~~~~~~~~~~~ drivers/tty/rocket.c:1412:2: warning: Value stored to 'cp' is never read cp = &info->channel; ^ ~~~~~~~~~~~~~~ drivers/tty/rocket.c:1730:2: warning: Value stored to 'cp' is never read cp = &info->channel; ^ ~~~~~~~~~~~~~~ drivers/tty/rocket.c:1825:3: warning: Value stored to 'str' is never read str = "8"; ^ ~~~ [many 'str' warnings stripped] drivers/tty/rocket.c:2037:3: warning: Value stored to 'board_type' is never read board_type = "RocketModem"; ^ ~~~~~~~~~~~~~ [some 'board_type' warnings stripped] Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/rocket.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 036feeb5e3f..13043e8d37f 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1380,7 +1380,6 @@ static void rp_send_xchar(struct tty_struct *tty, char ch) static void rp_throttle(struct tty_struct *tty) { struct r_port *info = tty->driver_data; - CHANNEL_t *cp; #ifdef ROCKET_DEBUG_THROTTLE printk(KERN_INFO "throttle %s: %d....\n", tty->name, @@ -1390,7 +1389,6 @@ static void rp_throttle(struct tty_struct *tty) if (rocket_paranoia_check(info, "rp_throttle")) return; - cp = &info->channel; if (I_IXOFF(tty)) rp_send_xchar(tty, STOP_CHAR(tty)); @@ -1400,7 +1398,6 @@ static void rp_throttle(struct tty_struct *tty) static void rp_unthrottle(struct tty_struct *tty) { struct r_port *info = tty->driver_data; - CHANNEL_t *cp; #ifdef ROCKET_DEBUG_THROTTLE printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, tty->ldisc.chars_in_buffer(tty)); @@ -1409,7 +1406,6 @@ static void rp_unthrottle(struct tty_struct *tty) if (rocket_paranoia_check(info, "rp_throttle")) return; - cp = &info->channel; if (I_IXOFF(tty)) rp_send_xchar(tty, START_CHAR(tty)); @@ -1722,13 +1718,10 @@ static int rp_write_room(struct tty_struct *tty) static int rp_chars_in_buffer(struct tty_struct *tty) { struct r_port *info = tty->driver_data; - CHANNEL_t *cp; if (rocket_paranoia_check(info, "rp_chars_in_buffer")) return 0; - cp = &info->channel; - #ifdef ROCKET_DEBUG_WRITE printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt); #endif @@ -1779,7 +1772,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) { int num_aiops, aiop, max_num_aiops, num_chan, chan; unsigned int aiopio[MAX_AIOPS_PER_BOARD]; - char *str, *board_type; CONTROLLER_t *ctlp; int fast_clock = 0; @@ -1800,7 +1792,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) /* Depending on the model, set up some config variables */ switch (dev->device) { case PCI_DEVICE_ID_RP4QUAD: - str = "Quadcable"; max_num_aiops = 1; ports_per_aiop = 4; rocketModel[i].model = MODEL_RP4QUAD; @@ -1808,42 +1799,36 @@ static __init int register_PCI(int i, struct pci_dev *dev) rocketModel[i].numPorts = 4; break; case PCI_DEVICE_ID_RP8OCTA: - str = "Octacable"; max_num_aiops = 1; rocketModel[i].model = MODEL_RP8OCTA; strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable"); rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_URP8OCTA: - str = "Octacable"; max_num_aiops = 1; rocketModel[i].model = MODEL_UPCI_RP8OCTA; strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable"); rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_RP8INTF: - str = "8"; max_num_aiops = 1; rocketModel[i].model = MODEL_RP8INTF; strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F"); rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_URP8INTF: - str = "8"; max_num_aiops = 1; rocketModel[i].model = MODEL_UPCI_RP8INTF; strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F"); rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_RP8J: - str = "8J"; max_num_aiops = 1; rocketModel[i].model = MODEL_RP8J; strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors"); rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_RP4J: - str = "4J"; max_num_aiops = 1; ports_per_aiop = 4; rocketModel[i].model = MODEL_RP4J; @@ -1851,56 +1836,48 @@ static __init int register_PCI(int i, struct pci_dev *dev) rocketModel[i].numPorts = 4; break; case PCI_DEVICE_ID_RP8SNI: - str = "8 (DB78 Custom)"; max_num_aiops = 1; rocketModel[i].model = MODEL_RP8SNI; strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78"); rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_RP16SNI: - str = "16 (DB78 Custom)"; max_num_aiops = 2; rocketModel[i].model = MODEL_RP16SNI; strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78"); rocketModel[i].numPorts = 16; break; case PCI_DEVICE_ID_RP16INTF: - str = "16"; max_num_aiops = 2; rocketModel[i].model = MODEL_RP16INTF; strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F"); rocketModel[i].numPorts = 16; break; case PCI_DEVICE_ID_URP16INTF: - str = "16"; max_num_aiops = 2; rocketModel[i].model = MODEL_UPCI_RP16INTF; strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F"); rocketModel[i].numPorts = 16; break; case PCI_DEVICE_ID_CRP16INTF: - str = "16"; max_num_aiops = 2; rocketModel[i].model = MODEL_CPCI_RP16INTF; strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F"); rocketModel[i].numPorts = 16; break; case PCI_DEVICE_ID_RP32INTF: - str = "32"; max_num_aiops = 4; rocketModel[i].model = MODEL_RP32INTF; strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F"); rocketModel[i].numPorts = 32; break; case PCI_DEVICE_ID_URP32INTF: - str = "32"; max_num_aiops = 4; rocketModel[i].model = MODEL_UPCI_RP32INTF; strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F"); rocketModel[i].numPorts = 32; break; case PCI_DEVICE_ID_RPP4: - str = "Plus Quadcable"; max_num_aiops = 1; ports_per_aiop = 4; altChanRingIndicator++; @@ -1910,7 +1887,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) rocketModel[i].numPorts = 4; break; case PCI_DEVICE_ID_RPP8: - str = "Plus Octacable"; max_num_aiops = 2; ports_per_aiop = 4; altChanRingIndicator++; @@ -1920,7 +1896,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) rocketModel[i].numPorts = 8; break; case PCI_DEVICE_ID_RP2_232: - str = "Plus 2 (RS-232)"; max_num_aiops = 1; ports_per_aiop = 2; altChanRingIndicator++; @@ -1930,7 +1905,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) rocketModel[i].numPorts = 2; break; case PCI_DEVICE_ID_RP2_422: - str = "Plus 2 (RS-422)"; max_num_aiops = 1; ports_per_aiop = 2; altChanRingIndicator++; @@ -1943,7 +1917,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) max_num_aiops = 1; ports_per_aiop = 6; - str = "6-port"; /* If revision is 1, the rocketmodem flash must be loaded. * If it is 2 it is a "socketed" version. */ @@ -1961,7 +1934,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) case PCI_DEVICE_ID_RP4M: max_num_aiops = 1; ports_per_aiop = 4; - str = "4-port"; if (dev->revision == 1) { rcktpt_type[i] = ROCKET_TYPE_MODEMII; rocketModel[i].loadrm2 = 1; @@ -1974,7 +1946,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) rocketModel[i].numPorts = 4; break; default: - str = "(unknown/unsupported)"; max_num_aiops = 0; break; } @@ -2000,14 +1971,12 @@ static __init int register_PCI(int i, struct pci_dev *dev) if (! (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) & PCI_GPIO_CTRL_8PORT)) { - str = "Quadcable"; ports_per_aiop = 4; rocketModel[i].numPorts = 4; } } break; case PCI_DEVICE_ID_UPCI_RM3_8PORT: - str = "8 ports"; max_num_aiops = 1; rocketModel[i].model = MODEL_UPCI_RM3_8PORT; strcpy(rocketModel[i].modelString, "RocketModem III 8 port"); @@ -2018,7 +1987,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) rcktpt_type[i] = ROCKET_TYPE_MODEMIII; break; case PCI_DEVICE_ID_UPCI_RM3_4PORT: - str = "4 ports"; max_num_aiops = 1; rocketModel[i].model = MODEL_UPCI_RM3_4PORT; strcpy(rocketModel[i].modelString, "RocketModem III 4 port"); @@ -2032,21 +2000,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) break; } - switch (rcktpt_type[i]) { - case ROCKET_TYPE_MODEM: - board_type = "RocketModem"; - break; - case ROCKET_TYPE_MODEMII: - board_type = "RocketModem II"; - break; - case ROCKET_TYPE_MODEMIII: - board_type = "RocketModem III"; - break; - default: - board_type = "RocketPort"; - break; - } - if (fast_clock) { sClockPrescale = 0x12; /* mod 2 (divide by 3) */ rp_baud_base[i] = 921600; -- cgit v1.2.2 From d55435037539837a741d54690427d37f96ed87fa Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 10:48:32 +0100 Subject: TTY: unify tty_init_dev fail path handling Change it so that we call the deinit functions at one place at the end of the function (by gotos). And while at it use some sane label names. This is a preparation for the deinitialization of tty in the next patch. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Julian Anastasov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 188632e4734..026bf2f6f5f 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1391,16 +1391,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, return ERR_PTR(-ENODEV); tty = alloc_tty_struct(); - if (!tty) - goto fail_no_mem; + if (!tty) { + retval = -ENOMEM; + goto err_module_put; + } initialize_tty_struct(tty, driver, idx); retval = tty_driver_install_tty(driver, tty); - if (retval < 0) { - free_tty_struct(tty); - module_put(driver->owner); - return ERR_PTR(retval); - } + if (retval < 0) + goto err_free_tty; /* * Structures all installed ... call the ldisc open routines. @@ -1409,15 +1408,17 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, */ retval = tty_ldisc_setup(tty, tty->link); if (retval) - goto release_mem_out; + goto err_release_tty; return tty; -fail_no_mem: +err_free_tty: + free_tty_struct(tty); +err_module_put: module_put(driver->owner); - return ERR_PTR(-ENOMEM); + return ERR_PTR(retval); /* call the tty release_tty routine to clean out this slot */ -release_mem_out: +err_release_tty: if (printk_ratelimit()) printk(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); -- cgit v1.2.2 From 8a1b8d70a07628f294f30485acf81971e3fcc755 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 10:48:33 +0100 Subject: TTY: unify pty_install fail path handling Change it so that we call the deinit functions at one place at the end of the function (by gotos). And while at it use some sane label names. This is a preparation for the deinitialization of tty in the next patch. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Julian Anastasov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 210774726ad..f5119184259 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -295,8 +295,8 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) return -ENOMEM; if (!try_module_get(driver->other->owner)) { /* This cannot in fact currently happen */ - free_tty_struct(o_tty); - return -ENOMEM; + retval = -ENOMEM; + goto err_free_tty; } initialize_tty_struct(o_tty, driver->other, idx); @@ -304,13 +304,11 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) the easy way .. */ retval = tty_init_termios(tty); if (retval) - goto free_mem_out; + goto err_module_put; retval = tty_init_termios(o_tty); - if (retval) { - tty_free_termios(tty); - goto free_mem_out; - } + if (retval) + goto err_free_termios; /* * Everything allocated ... set up the o_tty structure. @@ -327,10 +325,13 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) tty->count++; driver->ttys[idx] = tty; return 0; -free_mem_out: +err_free_termios: + tty_free_termios(tty); +err_module_put: module_put(o_tty->driver->owner); +err_free_tty: free_tty_struct(o_tty); - return -ENOMEM; + return retval; } static int pty_bsd_ioctl(struct tty_struct *tty, -- cgit v1.2.2 From c18d77aa00cde1215d9e045ba8f93004fe843f38 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 10:48:34 +0100 Subject: TTY: unify pty_unix98_install fail path handling Change it so that we call the deinit functions at one place at the end of the function (by gotos). And while at it use some sane label names. This is a preparation for the deinitialization of tty in the next patch. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Julian Anastasov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index f5119184259..b25d6c4014a 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -560,20 +560,19 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) return -ENOMEM; if (!try_module_get(driver->other->owner)) { /* This cannot in fact currently happen */ - free_tty_struct(o_tty); - return -ENOMEM; + goto err_free_tty; } initialize_tty_struct(o_tty, driver->other, idx); tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); if (tty->termios == NULL) - goto free_mem_out; + goto err_free_mem; *tty->termios = driver->init_termios; tty->termios_locked = tty->termios + 1; o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); if (o_tty->termios == NULL) - goto free_mem_out; + goto err_free_mem; *o_tty->termios = driver->other->init_termios; o_tty->termios_locked = o_tty->termios + 1; @@ -592,11 +591,12 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) tty->count++; pty_count++; return 0; -free_mem_out: +err_free_mem: kfree(o_tty->termios); + kfree(tty->termios); module_put(o_tty->driver->owner); +err_free_tty: free_tty_struct(o_tty); - kfree(tty->termios); return -ENOMEM; } -- cgit v1.2.2 From 6716671d8c1c07a8072098764d1b7cbfef7412ad Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 10:48:35 +0100 Subject: TTY: introduce deinit helpers for proper ldisc shutdown Introduce deinitialize_tty_struct which should be called after initialize_tty_struct and before successfull tty_ldisc_setup. It calls tty_ldisc_deinit which is opposite of tty_ldisc_init. It only puts a reference to ldisc and assigns NULL to tty->ldisc. It will be used to shut down ldisc when tty_release cannot be called yet. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Julian Anastasov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 14 ++++++++++++++ drivers/tty/tty_ldisc.c | 13 +++++++++++++ include/linux/tty.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 026bf2f6f5f..f5dd23520fe 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2886,6 +2886,20 @@ void initialize_tty_struct(struct tty_struct *tty, tty->dev = tty_get_device(tty); } +/** + * deinitialize_tty_struct + * @tty: tty to deinitialize + * + * This subroutine deinitializes a tty structure that has been newly + * allocated but tty_release cannot be called on that yet. + * + * Locking: none - tty in question must not be exposed at this point + */ +void deinitialize_tty_struct(struct tty_struct *tty) +{ + tty_ldisc_deinit(tty); +} + /** * tty_put_char - write one character to a tty * @tty: tty diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e19e1364711..5d01d32e2cf 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -956,6 +956,19 @@ void tty_ldisc_init(struct tty_struct *tty) tty_ldisc_assign(tty, ld); } +/** + * tty_ldisc_init - ldisc cleanup for new tty + * @tty: tty that was allocated recently + * + * The tty structure must not becompletely set up (tty_ldisc_setup) when + * this call is made. + */ +void tty_ldisc_deinit(struct tty_struct *tty) +{ + put_ldisc(tty->ldisc); + tty_ldisc_assign(tty, NULL); +} + void tty_ldisc_begin(void) { /* Setup the default TTY line discipline. */ diff --git a/include/linux/tty.h b/include/linux/tty.h index 9f469c70055..4db4ca79f89 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -472,6 +472,7 @@ extern int tty_add_file(struct tty_struct *tty, struct file *file); extern void free_tty_struct(struct tty_struct *tty); extern void initialize_tty_struct(struct tty_struct *tty, struct tty_driver *driver, int idx); +extern void deinitialize_tty_struct(struct tty_struct *tty); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, int first_ok); extern int tty_release(struct inode *inode, struct file *filp); @@ -525,6 +526,7 @@ extern int tty_set_ldisc(struct tty_struct *tty, int ldisc); extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_init(struct tty_struct *tty); +extern void tty_ldisc_deinit(struct tty_struct *tty); extern void tty_ldisc_begin(void); /* This last one is just for the tty layer internals and shouldn't be used elsewhere */ extern void tty_ldisc_enable(struct tty_struct *tty); -- cgit v1.2.2 From a9dccddb60913056bcadaeeacfe0395447fd2472 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 10:48:36 +0100 Subject: TTY: plug in deinitialize_tty_struct Used the newly introduced deinitialize_tty_struct to properly shut down ldisc. It is intended to fix the Julian's reported problem. He reports that kmemleak checker warns about memory leak: unreferenced object 0xc0e19860 (size 8): comm cat, pid 1226, jiffies 4294919464 (age 287.476s) hex dump (first 8 bytes): 44 de 2d c1 01 00 00 00 D.-..... backtrace: [] create_object+0x109/0x1ad [] kmem_cache_alloc+0x60/0x68 [] tty_ldisc_get+0x54/0x76 [] tty_ldisc_init+0xa/0x20 [] initialize_tty_struct+0x2d/0x1ac [] tty_init_dev+0x59/0x10d [] tty_open+0x24a/0x3a2 ... Signed-off-by: Jiri Slaby Cc: Alan Cox Reported-by: Julian Anastasov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 6 ++++-- drivers/tty/tty_io.c | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b25d6c4014a..21bddf359db 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -304,7 +304,7 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) the easy way .. */ retval = tty_init_termios(tty); if (retval) - goto err_module_put; + goto err_deinit_tty; retval = tty_init_termios(o_tty); if (retval) @@ -327,7 +327,8 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) return 0; err_free_termios: tty_free_termios(tty); -err_module_put: +err_deinit_tty: + deinitialize_tty_struct(o_tty); module_put(o_tty->driver->owner); err_free_tty: free_tty_struct(o_tty); @@ -592,6 +593,7 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) pty_count++; return 0; err_free_mem: + deinitialize_tty_struct(o_tty); kfree(o_tty->termios); kfree(tty->termios); module_put(o_tty->driver->owner); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index f5dd23520fe..8540f2bab9c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1399,7 +1399,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, retval = tty_driver_install_tty(driver, tty); if (retval < 0) - goto err_free_tty; + goto err_deinit_tty; /* * Structures all installed ... call the ldisc open routines. @@ -1411,7 +1411,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, goto err_release_tty; return tty; -err_free_tty: +err_deinit_tty: + deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: module_put(driver->owner); -- cgit v1.2.2 From 0259894c732837c801565d038eaecdcf8fc5bbe7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Mar 2011 10:48:37 +0100 Subject: TTY: fix fail path in tty_open When tty_add_file fails we omit to clean up. Fix that by calling tty_release appropriatelly. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 8540f2bab9c..55bb456e8f1 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1894,6 +1894,7 @@ got_driver: retval = tty_add_file(tty, filp); if (retval) { tty_unlock(); + tty_release(inode, filp); return retval; } -- cgit v1.2.2 From a664ec9675d77aa2196e797afa5516d3e476da77 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 28 Mar 2011 13:57:11 +0200 Subject: serial: altera_uart: Scan for a free port if platform device id is -1 Devices extracted from device tree all seem to have pdev->id set to -1. Up until now we mapped all devices with id -1 to the first device. This behaviour could lead to problems when using more than one Altera UART in a system. This patch changes the behaviour of the driver to scan for the next free id in case the id is -1. Because we cannot refer back to the assigned id in altera_uart_remove, the port instance needs to be stored in device drvdata. Reported-by: David Smoot Cc: Anton Vorontsov Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_uart.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 6d5b036ac78..50bc5a5ac65 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -540,11 +540,14 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) int i = pdev->id; int ret; - /* -1 emphasizes that the platform must have one port, no .N suffix */ - if (i == -1) - i = 0; + /* if id is -1 scan for a free id and use that one */ + if (i == -1) { + for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) + if (altera_uart_ports[i].port.mapbase == 0) + break; + } - if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) + if (i < 0 || i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) return -EINVAL; port = &altera_uart_ports[i].port; @@ -587,6 +590,8 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) port->ops = &altera_uart_ops; port->flags = UPF_BOOT_AUTOCONF; + dev_set_drvdata(&pdev->dev, port); + uart_add_one_port(&altera_uart_driver, port); return 0; @@ -594,14 +599,13 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) static int __devexit altera_uart_remove(struct platform_device *pdev) { - struct uart_port *port; - int i = pdev->id; + struct uart_port *port = dev_get_drvdata(&pdev->dev); - if (i == -1) - i = 0; - - port = &altera_uart_ports[i].port; - uart_remove_one_port(&altera_uart_driver, port); + if (port) { + uart_remove_one_port(&altera_uart_driver, port); + dev_set_drvdata(&pdev->dev, NULL); + port->mapbase = 0; + } return 0; } -- cgit v1.2.2 From 7c31bdb6b2a7118150df1668444fd1b7f1df3b85 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 29 Mar 2011 23:23:41 +0200 Subject: Char: moxa, do not touch NORMAL_ACTIVE bit The bit is set in tty_port_block_til_ready (via moxa_open) and unset in tty_port_close (via moxa_close). No need to pin it in the driver. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/moxa.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index ffdaab39314..a290e9ebafe 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1129,7 +1129,6 @@ static void moxa_shutdown(struct tty_port *port) struct moxa_port *ch = container_of(port, struct moxa_port, port); MoxaPortDisable(ch); MoxaPortFlushData(ch, 2); - clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); } static int moxa_carrier_raised(struct tty_port *port) @@ -1155,7 +1154,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) struct moxa_board_conf *brd; struct moxa_port *ch; int port; - int retval; port = tty->index; if (port == MAX_PORTS) { @@ -1190,10 +1188,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) mutex_unlock(&ch->port.mutex); mutex_unlock(&moxa_openlock); - retval = tty_port_block_til_ready(&ch->port, tty, filp); - if (retval == 0) - set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); - return retval; + return tty_port_block_til_ready(&ch->port, tty, filp); } static void moxa_close(struct tty_struct *tty, struct file *filp) -- cgit v1.2.2 From c7d7abff40c27f82fe78b1091ab3fad69b2546f9 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 30 Mar 2011 00:10:55 +0200 Subject: serial: core, move termios handling to uart_startup We should not fiddle with speed and cflags in .dtr_rts hook. Actually we might not have tty at that moment already. So move the console cflag copy and speed setup into uart_startup. Actually the speed setup is already there, but we need to call it unconditionally (uart_startup is called from uart_open with hw_init = 0). This means we move uart_change_speed before dtr/rts setup in .dtr_rts. But this should not matter as the setup should be called after uart_change_speed anyway. Before: After: dtr/rts setup (dtr_rts) uart_change_speed (startup) uart_change_speed (update_termios) dtr/rts setup (dtr_rts) dtr/rts setup (update_termios) dtr/rts setup (update_termios) The second setup will dismiss with the next patch. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index d6e72403449..47657cf4f8b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -172,12 +172,16 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in retval = uport->ops->startup(uport); if (retval == 0) { - if (init_hw) { - /* - * Initialise the hardware port settings. - */ - uart_change_speed(tty, state, NULL); + if (uart_console(uport) && uport->cons->cflag) { + tty->termios->c_cflag = uport->cons->cflag; + uport->cons->cflag = 0; + } + /* + * Initialise the hardware port settings. + */ + uart_change_speed(tty, state, NULL); + if (init_hw) { /* * Setup the RTS and DTR signals once the * port is open and ready to respond. @@ -1481,22 +1485,12 @@ static void uart_update_termios(struct tty_struct *tty, { struct uart_port *port = state->uart_port; - if (uart_console(port) && port->cons->cflag) { - tty->termios->c_cflag = port->cons->cflag; - port->cons->cflag = 0; - } - /* * If the device failed to grab its irq resources, * or some other error occurred, don't try to talk * to the port hardware. */ if (!(tty->flags & (1 << TTY_IO_ERROR))) { - /* - * Make termios settings take effect. - */ - uart_change_speed(tty, state, NULL); - /* * And finally enable the RTS and DTR signals. */ -- cgit v1.2.2 From 303a7a1199c20f7c9452f024a6e17bf348b6b398 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 30 Mar 2011 00:10:56 +0200 Subject: serial: core, do not set DTR/RTS twice on startup In .dtr_rts we do: uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS) and call uart_update_termios. It does: uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS) once again. As the only callsite of uart_update_termios is .dtr_rts, remove the uart_set_mctrl from uart_update_termios to not set it twice. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 47657cf4f8b..3aae8ed2a8f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1483,20 +1483,6 @@ static void uart_hangup(struct tty_struct *tty) static void uart_update_termios(struct tty_struct *tty, struct uart_state *state) { - struct uart_port *port = state->uart_port; - - /* - * If the device failed to grab its irq resources, - * or some other error occurred, don't try to talk - * to the port hardware. - */ - if (!(tty->flags & (1 << TTY_IO_ERROR))) { - /* - * And finally enable the RTS and DTR signals. - */ - if (tty->termios->c_cflag & CBAUD) - uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); - } } static int uart_carrier_raised(struct tty_port *port) -- cgit v1.2.2 From 6f5c24ad0f7619502199185a026a228174a27e68 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 30 Mar 2011 00:10:57 +0200 Subject: serial: core, remove uart_update_termios Now, uart_update_termios is empty, so it's time to remove it. We no longer need a live tty in .dtr_rts. So this should prune all the bugs where tty is zeroed in port->tty during tty_port_block_til_ready. There is one thing to note. We don't set ASYNC_NORMAL_ACTIVE now. It's because this is done already in tty_port_block_til_ready. Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 3aae8ed2a8f..d4bd465c4c4 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1470,21 +1470,6 @@ static void uart_hangup(struct tty_struct *tty) mutex_unlock(&port->mutex); } -/** - * uart_update_termios - update the terminal hw settings - * @tty: tty associated with UART - * @state: UART to update - * - * Copy across the serial console cflag setting into the termios settings - * for the initial open of the port. This allows continuity between the - * kernel settings, and the settings init adopts when it opens the port - * for the first time. - */ -static void uart_update_termios(struct tty_struct *tty, - struct uart_state *state) -{ -} - static int uart_carrier_raised(struct tty_port *port) { struct uart_state *state = container_of(port, struct uart_state, port); @@ -1504,16 +1489,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; - if (onoff) { + if (onoff) uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); - - /* - * If this is the first open to succeed, - * adjust things to suit. - */ - if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags)) - uart_update_termios(port->tty, state); - } else uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); } -- cgit v1.2.2 From 99edb3d10a9d384d69557bd09cc39b9ec62aa04e Mon Sep 17 00:00:00 2001 From: Jovi Zhang Date: Wed, 30 Mar 2011 05:30:41 -0400 Subject: tty: remove invalid location line in file header remove invalid location line in each file header after location moved from driver/char to driver/tty Signed-off-by: Jovi Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/amiserial.c | 2 -- drivers/tty/cyclades.c | 2 -- drivers/tty/ipwireless/Makefile | 2 -- drivers/tty/pty.c | 2 -- drivers/tty/serial/21285.c | 2 -- drivers/tty/serial/8250.c | 2 -- drivers/tty/serial/8250.h | 2 -- drivers/tty/serial/8250_accent.c | 2 -- drivers/tty/serial/8250_boca.c | 2 -- drivers/tty/serial/8250_exar_st16c554.c | 2 -- drivers/tty/serial/8250_fourport.c | 2 -- drivers/tty/serial/8250_hub6.c | 2 -- drivers/tty/serial/8250_mca.c | 2 -- drivers/tty/serial/8250_pci.c | 2 -- drivers/tty/serial/8250_pnp.c | 2 -- drivers/tty/serial/amba-pl010.c | 2 -- drivers/tty/serial/amba-pl011.c | 2 -- drivers/tty/serial/atmel_serial.c | 2 -- drivers/tty/serial/clps711x.c | 2 -- drivers/tty/serial/cpm_uart/cpm_uart.h | 2 -- drivers/tty/serial/cpm_uart/cpm_uart_core.c | 2 -- drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c | 2 -- drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h | 2 -- drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c | 2 -- drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h | 2 -- drivers/tty/serial/imx.c | 2 -- drivers/tty/serial/msm_serial.c | 2 +- drivers/tty/serial/msm_serial.h | 2 -- drivers/tty/serial/msm_smd_tty.c | 3 +-- drivers/tty/serial/netx-serial.c | 2 -- drivers/tty/serial/pmac_zilog.c | 2 -- drivers/tty/serial/pxa.c | 2 -- drivers/tty/serial/s3c2400.c | 3 +-- drivers/tty/serial/s3c2410.c | 3 +-- drivers/tty/serial/s3c2412.c | 3 +-- drivers/tty/serial/s3c2440.c | 3 +-- drivers/tty/serial/s3c24a0.c | 3 +-- drivers/tty/serial/s3c6400.c | 3 +-- drivers/tty/serial/s5pv210.c | 3 +-- drivers/tty/serial/sa1100.c | 2 -- drivers/tty/serial/samsung.c | 3 +-- drivers/tty/serial/samsung.h | 3 +-- drivers/tty/serial/sb1250-duart.c | 2 -- drivers/tty/serial/serial_core.c | 2 -- drivers/tty/serial/serial_ks8695.c | 2 -- drivers/tty/serial/serial_txx9.c | 2 -- drivers/tty/serial/sh-sci.c | 2 -- drivers/tty/serial/vt8500_serial.c | 2 -- drivers/tty/synclink.c | 2 -- drivers/tty/tty_io.c | 2 -- drivers/tty/tty_ioctl.c | 2 -- drivers/tty/tty_mutex.c | 3 --- drivers/tty/vt/keyboard.c | 2 -- drivers/tty/vt/selection.c | 2 -- drivers/tty/vt/vc_screen.c | 2 -- drivers/tty/vt/vt.c | 2 -- drivers/tty/vt/vt_ioctl.c | 2 -- 57 files changed, 11 insertions(+), 114 deletions(-) diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index f214e502247..220579592c2 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/amiserial.c - * * Serial driver for the amiga builtin port. * * This code was created by taking serial.c version 4.30 from kernel diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index e6f20d24e26..bfa05e80182 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -3,8 +3,6 @@ #undef Z_EXT_CHARS_IN_BUFFER /* - * linux/drivers/char/cyclades.c - * * This file contains the driver for the Cyclades async multiport * serial boards. * diff --git a/drivers/tty/ipwireless/Makefile b/drivers/tty/ipwireless/Makefile index db80873d7f2..fe2e1730986 100644 --- a/drivers/tty/ipwireless/Makefile +++ b/drivers/tty/ipwireless/Makefile @@ -1,6 +1,4 @@ # -# drivers/char/pcmcia/ipwireless/Makefile -# # Makefile for the IPWireless driver # diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 21bddf359db..98b6e3bdb00 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/pty.c - * * Copyright (C) 1991, 1992 Linus Torvalds * * Added support for a Unix98-style ptmx device. diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index d89aa38c5cf..1b37626e8f1 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/21285.c - * * Driver for the serial port on the 21285 StrongArm-110 core logic chip. * * Based on drivers/char/serial.c diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 6611535f444..54482d724fe 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/8250.c - * * Driver for 8250/16550-type serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h index 6e19ea3e48d..d13b586c0f7 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250.h @@ -1,6 +1,4 @@ /* - * linux/drivers/char/8250.h - * * Driver for 8250/16550-type serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250_accent.c index 9c10262f246..34b51c65119 100644 --- a/drivers/tty/serial/8250_accent.c +++ b/drivers/tty/serial/8250_accent.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/8250_accent.c - * * Copyright (C) 2005 Russell King. * Data taken from include/asm-i386/serial.h * diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250_boca.c index 3bfe0f7b26f..d125dc10798 100644 --- a/drivers/tty/serial/8250_boca.c +++ b/drivers/tty/serial/8250_boca.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/8250_boca.c - * * Copyright (C) 2005 Russell King. * Data taken from include/asm-i386/serial.h * diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250_exar_st16c554.c index 567143ace15..bf53aabf9b5 100644 --- a/drivers/tty/serial/8250_exar_st16c554.c +++ b/drivers/tty/serial/8250_exar_st16c554.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/8250_exar.c - * * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com > * Based on 8250_boca. * diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250_fourport.c index 6375d68b791..be158260962 100644 --- a/drivers/tty/serial/8250_fourport.c +++ b/drivers/tty/serial/8250_fourport.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/8250_fourport.c - * * Copyright (C) 2005 Russell King. * Data taken from include/asm-i386/serial.h * diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250_hub6.c index 7609150e7d5..a5c778e83de 100644 --- a/drivers/tty/serial/8250_hub6.c +++ b/drivers/tty/serial/8250_hub6.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/8250_hub6.c - * * Copyright (C) 2005 Russell King. * Data taken from include/asm-i386/serial.h * diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250_mca.c index d10be944ad4..d20abf04541 100644 --- a/drivers/tty/serial/8250_mca.c +++ b/drivers/tty/serial/8250_mca.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/8250_mca.c - * * Copyright (C) 2005 Russell King. * Data taken from include/asm-i386/serial.h * diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 738cec9807d..98311ac815c 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/8250_pci.c - * * Probe module for 8250/16550-type PCI serial ports. * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250_pnp.c index 4822cb50cd0..fc301f6722e 100644 --- a/drivers/tty/serial/8250_pnp.c +++ b/drivers/tty/serial/8250_pnp.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/8250_pnp.c - * * Probe module for 8250/16550-type ISAPNP serial ports. * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index d742dd2c525..c0d10c4ddb7 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/amba.c - * * Driver for AMBA serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 6deee4e546b..8dc0541feec 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/amba.c - * * Driver for AMBA serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index f119d176110..652bdac8ce8 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/atmel_serial.c - * * Driver for Atmel AT91 / AT32 Serial ports * Copyright (C) 2003 Rick Bronson * diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index b6acd19b458..e6c3dbd781d 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/clps711x.c - * * Driver for CLPS711x serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h index b754dcf0fda..cf34d26ff6c 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart.h @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/cpm_uart.h - * * Driver for CPM (SCC/SMC) serial ports * * Copyright (C) 2004 Freescale Semiconductor, Inc. diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index a9a6a5fd169..9488da74d4f 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/cpm_uart.c - * * Driver for CPM (SCC/SMC) serial ports; core driver * * Based on arch/ppc/cpm2_io/uart.c by Dan Malek diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c index 3fc1d66e32c..18f79575894 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/cpm_uart.c - * * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions * * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h index 10eecd6af6d..60c7e94cde1 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/cpm_uart/cpm_uart_cpm1.h - * * Driver for CPM (SCC/SMC) serial ports * * definitions for cpm1 diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c index 814ac006393..a4927e66e74 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/cpm_uart_cpm2.c - * * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions * * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h index 7194c63dcf5..51e651a6993 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/cpm_uart/cpm_uart_cpm2.h - * * Driver for CPM (SCC/SMC) serial ports * * definitions for cpm2 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index cb36b0d4ef3..df6828654f4 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/imx.c - * * Driver for Motorola IMX serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index bfee9b4c666..e6ba8387650 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1,5 +1,5 @@ /* - * drivers/serial/msm_serial.c - driver for msm7k serial device and console + * Driver for msm7k serial device and console * * Copyright (C) 2007 Google, Inc. * Author: Robert Love diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h index 9b8dc5d0d85..e4acef5de77 100644 --- a/drivers/tty/serial/msm_serial.h +++ b/drivers/tty/serial/msm_serial.h @@ -1,6 +1,4 @@ /* - * drivers/serial/msm_serial.h - * * Copyright (C) 2007 Google, Inc. * Author: Robert Love * Copyright (c) 2011, Code Aurora Forum. All rights reserved. diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c index beeff1e8609..4f41dcdcb77 100644 --- a/drivers/tty/serial/msm_smd_tty.c +++ b/drivers/tty/serial/msm_smd_tty.c @@ -1,5 +1,4 @@ -/* drivers/tty/serial/msm_smd_tty.c - * +/* * Copyright (C) 2007 Google, Inc. * Copyright (c) 2011, Code Aurora Forum. All rights reserved. * Author: Brian Swetland diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c index 7735c9f35fa..d40da78e7c8 100644 --- a/drivers/tty/serial/netx-serial.c +++ b/drivers/tty/serial/netx-serial.c @@ -1,6 +1,4 @@ /* - * drivers/serial/netx-serial.c - * * Copyright (c) 2005 Sascha Hauer , Pengutronix * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index e1c8d4f1ce5..5acd24a27d0 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/pmac_zilog.c - * * Driver for PowerMac Z85c30 based ESCC cell found in the * "macio" ASICs of various PowerMac models * diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 1102a39b44f..4302e6e3768 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -1,6 +1,4 @@ /* - * linux/drivers/serial/pxa.c - * * Based on drivers/serial/8250.c by Russell King. * * Author: Nicolas Pitre diff --git a/drivers/tty/serial/s3c2400.c b/drivers/tty/serial/s3c2400.c index fed1a9a1ffb..d13051b3df8 100644 --- a/drivers/tty/serial/s3c2400.c +++ b/drivers/tty/serial/s3c2400.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s3c240.c - * +/* * Driver for Samsung SoC onboard UARTs. * * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c index 73f089d3efd..bffe6ff9b15 100644 --- a/drivers/tty/serial/s3c2410.c +++ b/drivers/tty/serial/s3c2410.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s3c2410.c - * +/* * Driver for Samsung S3C2410 SoC onboard UARTs. * * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c index 1700b1a2fb7..7e2b9504a68 100644 --- a/drivers/tty/serial/s3c2412.c +++ b/drivers/tty/serial/s3c2412.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s3c2412.c - * +/* * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs. * * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c index 094cc3904b1..9e10d415d5f 100644 --- a/drivers/tty/serial/s3c2440.c +++ b/drivers/tty/serial/s3c2440.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s3c2440.c - * +/* * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs. * * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics diff --git a/drivers/tty/serial/s3c24a0.c b/drivers/tty/serial/s3c24a0.c index fad6083ca42..914eff22e49 100644 --- a/drivers/tty/serial/s3c24a0.c +++ b/drivers/tty/serial/s3c24a0.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s3c24a0.c - * +/* * Driver for Samsung S3C24A0 SoC onboard UARTs. * * Based on drivers/serial/s3c2410.c diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c index 4be92ab5005..ded26c42ff3 100644 --- a/drivers/tty/serial/s3c6400.c +++ b/drivers/tty/serial/s3c6400.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s3c6400.c - * +/* * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. * * Copyright 2008 Openmoko, Inc. diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c index 6ebccd70a70..fb2619f93d8 100644 --- a/drivers/tty/serial/s5pv210.c +++ b/drivers/tty/serial/s5pv210.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/s5pv210.c - * +/* * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index 2199d819a98..ef7a21a6a01 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/sa1100.c - * * Driver for SA11x0 serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 9e2fa8d784e..f66f6482930 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1,5 +1,4 @@ -/* linux/drivers/serial/samsuing.c - * +/* * Driver core for Samsung SoC onboard UARTs. * * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index 0ac06a07d25..5b098cd7604 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h @@ -1,5 +1,4 @@ -/* linux/drivers/serial/samsung.h - * +/* * Driver for Samsung SoC onboard UARTs. * * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 602d9845c52..ea2340b814e 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -1,6 +1,4 @@ /* - * drivers/serial/sb1250-duart.c - * * Support for the asynchronous serial interface (DUART) included * in the BCM1250 and derived System-On-a-Chip (SOC) devices. * diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index d4bd465c4c4..1d7aedca05b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/core.c - * * Driver core for serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c index b1962025b1a..2430319f2f5 100644 --- a/drivers/tty/serial/serial_ks8695.c +++ b/drivers/tty/serial/serial_ks8695.c @@ -1,6 +1,4 @@ /* - * drivers/serial/serial_ks8695.c - * * Driver for KS8695 serial ports * * Based on drivers/serial/serial_amba.c, by Kam Lee. diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index c50e9fbbf74..8e3fc1944e6 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -1,6 +1,4 @@ /* - * drivers/serial/serial_txx9.c - * * Derived from many drivers using generic_serial interface, * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c * (was in Linux/VR tree) by Jim Pick. diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 920a6f929c8..f35b8fb94b8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1,6 +1,4 @@ /* - * drivers/serial/sh-sci.c - * * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * * Copyright (C) 2002 - 2011 Paul Mundt diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 322bf56c0d8..37fc4e3d487 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -1,6 +1,4 @@ /* - * drivers/serial/vt8500_serial.c - * * Copyright (C) 2010 Alexey Charkov * * Based on msm_serial.c, which is: diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 27da23d98e3..272e417a9b0 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/synclink.c - * * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 55bb456e8f1..3f4ad988543 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/tty_io.c - * * Copyright (C) 1991, 1992 Linus Torvalds */ diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 21574cb3234..ef44ddcb137 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/tty_ioctl.c - * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 133697540c7..3b2bb771944 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -1,6 +1,3 @@ -/* - * drivers/char/tty_lock.c - */ #include #include #include diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index d6b342b5b42..3761ccf0f34 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/keyboard.c - * * Written for linux by Johan Myreen as a translation from * the assembly version by Linus (with diacriticals added) * diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index adf0ad2a885..fb864e7fcd1 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/selection.c - * * This module exports the functions: * * 'int set_selection(struct tiocl_selection __user *, struct tty_struct *)' diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 1564261e80c..66825c9f516 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/vc_screen.c - * * Provide access to virtual console memory. * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled) * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index f287dca0d9d..a48da206306 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/vt.c - * * Copyright (C) 1991, 1992 Linus Torvalds */ diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 54851544d7c..5e096f43bce 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -1,6 +1,4 @@ /* - * linux/drivers/char/vt_ioctl.c - * * Copyright (C) 1992 obz under the linux copyright * * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 -- cgit v1.2.2 From d94206028854ba4c891004cecdbb2e220bf277bb Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 10 Apr 2011 19:22:34 +0200 Subject: Serial: ifx6x60c: Remove duplicate includes of linux/tty.h Including linux/tty.h 3 times is a little over the top - once will do. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 8ee5a41d340..5315525220f 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -56,7 +55,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.2 From f8df13e0a901fe55631fed66562369b4dba40f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Fri, 15 Apr 2011 10:08:08 +0200 Subject: tty: Clean console safely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Traditional \E[2J sequence erases console display but scroll-back buffer and underlying device (frame) buffer keep data that can be accessed by scrolling console back. This patch introduce new \E[J parameter 3 that allows to scramble scroll-back buffer explicitly. Session locking programs (screen, vlock) can use it to prevent attacker to browse locked console history. Signed-off-by: Petr Písař Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index a48da206306..b3915b7ad3e 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1193,6 +1193,13 @@ static void csi_J(struct vc_data *vc, int vpar) vc->vc_x + 1); } break; + case 3: /* erase scroll-back buffer (and whole display) */ + scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, + vc->vc_screenbuf_size >> 1); + set_origin(vc); + if (CON_IS_VISIBLE(vc)) + update_screen(vc); + /* fall through */ case 2: /* erase whole display */ count = vc->vc_cols * vc->vc_rows; start = (unsigned short *)vc->vc_origin; -- cgit v1.2.2 From e9a470f445271eb157ee860a93b062324402fc3a Mon Sep 17 00:00:00 2001 From: "Govindraj.R" Date: Mon, 18 Apr 2011 20:27:35 +0530 Subject: Serial: Remove unused code. Remove stale code in serial_core layer. Cc: Alan Cox Signed-off-by: Govindraj.R Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1d7aedca05b..55965d5b814 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1242,17 +1242,6 @@ static void uart_set_termios(struct tty_struct *tty, } spin_unlock_irqrestore(&state->uart_port->lock, flags); } -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&state->uart_port.open_wait); -#endif } /* -- cgit v1.2.2 From b1c43f82c5aa265442f82dba31ce985ebb7aa71c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 Mar 2011 12:25:08 +0200 Subject: tty: make receive_buf() return the amout of bytes received it makes it simpler to keep track of the amount of bytes received and simplifies how flush_to_ldisc counts the remaining bytes. It also fixes a bug of lost bytes on n_tty when flushing too many bytes via the USB serial gadget driver. Tested-by: Stefan Bigler Tested-by: Toby Gray Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_ldisc.c | 12 +++++--- drivers/input/serio/serport.c | 10 +++++-- drivers/isdn/gigaset/ser-gigaset.c | 8 +++-- drivers/misc/ti-st/st_core.c | 6 ++-- drivers/net/caif/caif_serial.c | 6 ++-- drivers/net/can/slcan.c | 9 ++++-- drivers/net/hamradio/6pack.c | 8 +++-- drivers/net/hamradio/mkiss.c | 11 ++++--- drivers/net/irda/irtty-sir.c | 16 +++++----- drivers/net/ppp_async.c | 6 ++-- drivers/net/ppp_synctty.c | 6 ++-- drivers/net/slip.c | 11 ++++--- drivers/net/wan/x25_asy.c | 7 +++-- drivers/tty/n_gsm.c | 6 ++-- drivers/tty/n_hdlc.c | 18 ++++++----- drivers/tty/n_r3964.c | 10 ++++--- drivers/tty/n_tty.c | 61 +++++++++----------------------------- drivers/tty/tty_buffer.c | 15 ++++++---- drivers/tty/vt/selection.c | 3 +- include/linux/tty_ldisc.h | 9 +++--- 20 files changed, 125 insertions(+), 113 deletions(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 48ad2a7ab08..0d4da5e14ba 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -357,22 +357,26 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) * * Return Value: None */ -static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) +static unsigned int hci_uart_tty_receive(struct tty_struct *tty, + const u8 *data, char *flags, int count) { struct hci_uart *hu = (void *)tty->disc_data; + int received; if (!hu || tty != hu->tty) - return; + return -ENODEV; if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) - return; + return -EINVAL; spin_lock(&hu->rx_lock); - hu->proto->recv(hu, (void *) data, count); + received = hu->proto->recv(hu, (void *) data, count); hu->hdev->stat.byte_rx += count; spin_unlock(&hu->rx_lock); tty_unthrottle(tty); + + return received; } static int hci_uart_register_dev(struct hci_uart *hu) diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 8755f5f3ad3..f3698967edf 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -120,17 +120,21 @@ static void serport_ldisc_close(struct tty_struct *tty) * 'interrupt' routine. */ -static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) +static unsigned int serport_ldisc_receive(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct serport *serport = (struct serport*) tty->disc_data; unsigned long flags; unsigned int ch_flags; + int ret = 0; int i; spin_lock_irqsave(&serport->lock, flags); - if (!test_bit(SERPORT_ACTIVE, &serport->flags)) + if (!test_bit(SERPORT_ACTIVE, &serport->flags)) { + ret = -EINVAL; goto out; + } for (i = 0; i < count; i++) { switch (fp[i]) { @@ -152,6 +156,8 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c out: spin_unlock_irqrestore(&serport->lock, flags); + + return ret == 0 ? count : ret; } /* diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 86a5c4f7775..1d44d470897 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -674,7 +674,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, * cflags buffer containing error flags for received characters (ignored) * count number of received characters */ -static void +static unsigned int gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, char *cflags, int count) { @@ -683,12 +683,12 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, struct inbuf_t *inbuf; if (!cs) - return; + return -ENODEV; inbuf = cs->inbuf; if (!inbuf) { dev_err(cs->dev, "%s: no inbuf\n", __func__); cs_put(cs); - return; + return -EINVAL; } tail = inbuf->tail; @@ -725,6 +725,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, gig_dbg(DEBUG_INTR, "%s-->BH", __func__); gigaset_schedule_event(cs); cs_put(cs); + + return count; } /* diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 486117f72c9..cb98a7da98e 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -744,8 +744,8 @@ static void st_tty_close(struct tty_struct *tty) pr_debug("%s: done ", __func__); } -static void st_tty_receive(struct tty_struct *tty, const unsigned char *data, - char *tty_flags, int count) +static unsigned int st_tty_receive(struct tty_struct *tty, + const unsigned char *data, char *tty_flags, int count) { #ifdef VERBOSE print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE, @@ -758,6 +758,8 @@ static void st_tty_receive(struct tty_struct *tty, const unsigned char *data, */ st_recv(tty->disc_data, data, count); pr_debug("done %s", __func__); + + return count; } /* wake-up function called in from the TTY layer diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 3df0c0f8b8b..73c7e03617e 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -167,8 +167,8 @@ static inline void debugfs_tx(struct ser_device *ser, const u8 *data, int size) #endif -static void ldisc_receive(struct tty_struct *tty, const u8 *data, - char *flags, int count) +static unsigned int ldisc_receive(struct tty_struct *tty, + const u8 *data, char *flags, int count) { struct sk_buff *skb = NULL; struct ser_device *ser; @@ -215,6 +215,8 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data, } else ++ser->dev->stats.rx_dropped; update_tty_status(ser); + + return count; } static int handle_tx(struct ser_device *ser) diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index b423965a78d..c600954998d 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -425,16 +425,17 @@ static void slc_setup(struct net_device *dev) * in parallel */ -static void slcan_receive_buf(struct tty_struct *tty, +static unsigned int slcan_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct slcan *sl = (struct slcan *) tty->disc_data; + int bytes = count; if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) - return; + return -ENODEV; /* Read the characters out of the buffer */ - while (count--) { + while (bytes--) { if (fp && *fp++) { if (!test_and_set_bit(SLF_ERROR, &sl->flags)) sl->dev->stats.rx_errors++; @@ -443,6 +444,8 @@ static void slcan_receive_buf(struct tty_struct *tty, } slcan_unesc(sl, *cp++); } + + return count; } /************************************ diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 3e5d0b6b651..992089639ea 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -456,7 +456,7 @@ out: * a block of 6pack data has been received, which can now be decapsulated * and sent on to some IP layer for further processing. */ -static void sixpack_receive_buf(struct tty_struct *tty, +static unsigned int sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct sixpack *sp; @@ -464,11 +464,11 @@ static void sixpack_receive_buf(struct tty_struct *tty, int count1; if (!count) - return; + return 0; sp = sp_get(tty); if (!sp) - return; + return -ENODEV; memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf)); @@ -487,6 +487,8 @@ static void sixpack_receive_buf(struct tty_struct *tty, sp_put(sp); tty_unthrottle(tty); + + return count1; } /* diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 4c628393c8b..0e4f2353114 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -923,13 +923,14 @@ static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file, * a block of data has been received, which can now be decapsulated * and sent on to the AX.25 layer for further processing. */ -static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static unsigned int mkiss_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct mkiss *ax = mkiss_get(tty); + int bytes = count; if (!ax) - return; + return -ENODEV; /* * Argh! mtu change time! - costs us the packet part received @@ -939,7 +940,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, ax_changedmtu(ax); /* Read the characters out of the buffer */ - while (count--) { + while (bytes--) { if (fp != NULL && *fp++) { if (!test_and_set_bit(AXF_ERROR, &ax->flags)) ax->dev->stats.rx_errors++; @@ -952,6 +953,8 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, mkiss_put(ax); tty_unthrottle(tty); + + return count; } /* diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 3352b2443e5..035861d8acb 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -216,23 +216,23 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t * usbserial: urb-complete-interrupt / softint */ -static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static unsigned int irtty_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct sir_dev *dev; struct sirtty_cb *priv = tty->disc_data; int i; - IRDA_ASSERT(priv != NULL, return;); - IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); + IRDA_ASSERT(priv != NULL, return -ENODEV;); + IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EINVAL;); if (unlikely(count==0)) /* yes, this happens */ - return; + return 0; dev = priv->dev; if (!dev) { IRDA_WARNING("%s(), not ready yet!\n", __func__); - return; + return -ENODEV; } for (i = 0; i < count; i++) { @@ -242,11 +242,13 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, if (fp && *fp++) { IRDA_DEBUG(0, "Framing or parity error!\n"); sirdev_receive(dev, NULL, 0); /* notify sir_dev (updating stats) */ - return; + return -EINVAL; } } sirdev_receive(dev, cp, count); + + return count; } /* diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index a1b82c9c67d..53872d7d738 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -340,7 +340,7 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) } /* May sleep, don't call from interrupt level or with interrupts disabled */ -static void +static unsigned int ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, char *cflags, int count) { @@ -348,7 +348,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, unsigned long flags; if (!ap) - return; + return -ENODEV; spin_lock_irqsave(&ap->recv_lock, flags); ppp_async_input(ap, buf, cflags, count); spin_unlock_irqrestore(&ap->recv_lock, flags); @@ -356,6 +356,8 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, tasklet_schedule(&ap->tsk); ap_put(ap); tty_unthrottle(tty); + + return count; } static void diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 2573f525f11..0815790a5cf 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -381,7 +381,7 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait) } /* May sleep, don't call from interrupt level or with interrupts disabled */ -static void +static unsigned int ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, char *cflags, int count) { @@ -389,7 +389,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, unsigned long flags; if (!ap) - return; + return -ENODEV; spin_lock_irqsave(&ap->recv_lock, flags); ppp_sync_input(ap, buf, cflags, count); spin_unlock_irqrestore(&ap->recv_lock, flags); @@ -397,6 +397,8 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, tasklet_schedule(&ap->tsk); sp_put(ap); tty_unthrottle(tty); + + return count; } static void diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 86cbb9ea2f2..86718d35839 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -670,16 +670,17 @@ static void sl_setup(struct net_device *dev) * in parallel */ -static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static unsigned int slip_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct slip *sl = tty->disc_data; + int bytes = count; if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) - return; + return -ENODEV; /* Read the characters out of the buffer */ - while (count--) { + while (bytes--) { if (fp && *fp++) { if (!test_and_set_bit(SLF_ERROR, &sl->flags)) sl->dev->stats.rx_errors++; @@ -693,6 +694,8 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, #endif slip_unesc(sl, *cp++); } + + return count; } /************************************ diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 24297b274cd..40398bf7d03 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -517,17 +517,18 @@ static int x25_asy_close(struct net_device *dev) * and sent on to some IP layer for further processing. */ -static void x25_asy_receive_buf(struct tty_struct *tty, +static unsigned int x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct x25_asy *sl = tty->disc_data; + int bytes = count; if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev)) return; /* Read the characters out of the buffer */ - while (count--) { + while (bytes--) { if (fp && *fp++) { if (!test_and_set_bit(SLF_ERROR, &sl->flags)) sl->dev->stats.rx_errors++; @@ -536,6 +537,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, } x25_asy_unesc(sl, *cp++); } + + return count; } /* diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 47f8cdb207f..6abc7359884 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2138,8 +2138,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) gsm->tty = NULL; } -static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static unsigned int gsmld_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct gsm_mux *gsm = tty->disc_data; const unsigned char *dp; @@ -2173,6 +2173,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, } /* FASYNC if needed ? */ /* If clogged call tty_throttle(tty); */ + + return count; } /** diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index cea56033b34..cac666314ae 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -188,8 +188,8 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait); static int n_hdlc_tty_open(struct tty_struct *tty); static void n_hdlc_tty_close(struct tty_struct *tty); -static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp, - char *fp, int count); +static unsigned int n_hdlc_tty_receive(struct tty_struct *tty, + const __u8 *cp, char *fp, int count); static void n_hdlc_tty_wakeup(struct tty_struct *tty); #define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) @@ -509,8 +509,8 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) * Called by tty low level driver when receive data is available. Data is * interpreted as one HDLC frame. */ -static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, - char *flags, int count) +static unsigned int n_hdlc_tty_receive(struct tty_struct *tty, + const __u8 *data, char *flags, int count) { register struct n_hdlc *n_hdlc = tty2n_hdlc (tty); register struct n_hdlc_buf *buf; @@ -521,20 +521,20 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, /* This can happen if stuff comes in on the backup tty */ if (!n_hdlc || tty != n_hdlc->tty) - return; + return -ENODEV; /* verify line is using HDLC discipline */ if (n_hdlc->magic != HDLC_MAGIC) { printk("%s(%d) line not using HDLC discipline\n", __FILE__,__LINE__); - return; + return -EINVAL; } if ( count>maxframe ) { if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d) rx count>maxframesize, data discarded\n", __FILE__,__LINE__); - return; + return -EINVAL; } /* get a free HDLC buffer */ @@ -550,7 +550,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d) no more rx buffers, data discarded\n", __FILE__,__LINE__); - return; + return -EINVAL; } /* copy received data to HDLC buffer */ @@ -565,6 +565,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, if (n_hdlc->tty->fasync != NULL) kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); + return count; + } /* end of n_hdlc_tty_receive() */ /** diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 5c6c31459a2..a4bc39c21a4 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -139,8 +139,8 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file, static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, struct poll_table_struct *wait); -static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count); +static unsigned int r3964_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count); static struct tty_ldisc_ops tty_ldisc_N_R3964 = { .owner = THIS_MODULE, @@ -1239,8 +1239,8 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, return result; } -static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static unsigned int r3964_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct r3964_info *pInfo = tty->disc_data; const unsigned char *p; @@ -1257,6 +1257,8 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, } } + + return count; } MODULE_LICENSE("GPL"); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0ad32888091..95d0a9c2dd1 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -81,38 +81,6 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, return put_user(x, ptr); } -/** - * n_tty_set__room - receive space - * @tty: terminal - * - * Called by the driver to find out how much data it is - * permitted to feed to the line discipline without any being lost - * and thus to manage flow control. Not serialized. Answers for the - * "instant". - */ - -static void n_tty_set_room(struct tty_struct *tty) -{ - /* tty->read_cnt is not read locked ? */ - int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; - int old_left; - - /* - * If we are doing input canonicalization, and there are no - * pending newlines, let characters through without limit, so - * that erase characters will be handled. Other excess - * characters will be beeped. - */ - if (left <= 0) - left = tty->icanon && !tty->canon_data; - old_left = tty->receive_room; - tty->receive_room = left; - - /* Did this open up the receive buffer? We may need to flip */ - if (left && !old_left) - schedule_work(&tty->buf.work); -} - static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) { if (tty->read_cnt < N_TTY_BUF_SIZE) { @@ -184,7 +152,6 @@ static void reset_buffer_flags(struct tty_struct *tty) tty->canon_head = tty->canon_data = tty->erasing = 0; memset(&tty->read_flags, 0, sizeof tty->read_flags); - n_tty_set_room(tty); check_unthrottle(tty); } @@ -1360,17 +1327,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty) * calls one at a time and in order (or using flush_to_ldisc) */ -static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static unsigned int n_tty_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { const unsigned char *p; char *f, flags = TTY_NORMAL; int i; char buf[64]; unsigned long cpuflags; + int left; + int ret = 0; if (!tty->read_buf) - return; + return 0; if (tty->real_raw) { spin_lock_irqsave(&tty->read_lock, cpuflags); @@ -1380,6 +1349,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, memcpy(tty->read_buf + tty->read_head, cp, i); tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1); tty->read_cnt += i; + ret += i; cp += i; count -= i; @@ -1389,8 +1359,10 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, memcpy(tty->read_buf + tty->read_head, cp, i); tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1); tty->read_cnt += i; + ret += i; spin_unlock_irqrestore(&tty->read_lock, cpuflags); } else { + ret = count; for (i = count, p = cp, f = fp; i; i--, p++) { if (f) flags = *f++; @@ -1418,8 +1390,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, tty->ops->flush_chars(tty); } - n_tty_set_room(tty); - if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || L_EXTPROC(tty)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); @@ -1432,8 +1402,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, * mode. We don't want to throttle the driver if we're in * canonical mode and don't have a newline yet! */ - if (tty->receive_room < TTY_THRESHOLD_THROTTLE) + left = N_TTY_BUF_SIZE - tty->read_cnt - 1; + + if (left < TTY_THRESHOLD_THROTTLE) tty_throttle(tty); + + return ret; } int is_ignored(int sig) @@ -1477,7 +1451,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { tty->raw = 1; tty->real_raw = 1; - n_tty_set_room(tty); return; } if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || @@ -1530,7 +1503,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) else tty->real_raw = 0; } - n_tty_set_room(tty); /* The termios change make the tty ready for I/O */ wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->read_wait); @@ -1812,8 +1784,6 @@ do_it_again: retval = -ERESTARTSYS; break; } - /* FIXME: does n_tty_set_room need locking ? */ - n_tty_set_room(tty); timeout = schedule_timeout(timeout); continue; } @@ -1885,10 +1855,8 @@ do_it_again: * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, * we won't get any more characters. */ - if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) { - n_tty_set_room(tty); + if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) check_unthrottle(tty); - } if (b - buf >= minimum) break; @@ -1910,7 +1878,6 @@ do_it_again: } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) goto do_it_again; - n_tty_set_room(tty); return retval; } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1a7918d71a..46de2e075da 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -416,6 +416,7 @@ static void flush_to_ldisc(struct work_struct *work) struct tty_buffer *head, *tail = tty->buf.tail; int seen_tail = 0; while ((head = tty->buf.head) != NULL) { + int copied; int count; char *char_buf; unsigned char *flag_buf; @@ -442,17 +443,19 @@ static void flush_to_ldisc(struct work_struct *work) line discipline as we want to empty the queue */ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) break; - if (!tty->receive_room || seen_tail) - break; - if (count > tty->receive_room) - count = tty->receive_room; char_buf = head->char_buf_ptr + head->read; flag_buf = head->flag_buf_ptr + head->read; - head->read += count; spin_unlock_irqrestore(&tty->buf.lock, flags); - disc->ops->receive_buf(tty, char_buf, + copied = disc->ops->receive_buf(tty, char_buf, flag_buf, count); spin_lock_irqsave(&tty->buf.lock, flags); + + head->read += copied; + + if (copied == 0 || seen_tail) { + schedule_work(&tty->buf.work); + break; + } } clear_bit(TTY_FLUSHING, &tty->flags); } diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index fb864e7fcd1..67b1d0d7c8a 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -332,8 +332,7 @@ int paste_selection(struct tty_struct *tty) continue; } count = sel_buffer_lth - pasted; - count = min(count, tty->receive_room); - tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, + count = tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, NULL, count); pasted += count; } diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index ff7dc08696a..5b07792ccb4 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -76,7 +76,7 @@ * tty device. It is solely the responsibility of the line * discipline to handle poll requests. * - * void (*receive_buf)(struct tty_struct *, const unsigned char *cp, + * unsigned int (*receive_buf)(struct tty_struct *, const unsigned char *cp, * char *fp, int count); * * This function is called by the low-level tty driver to send @@ -84,7 +84,8 @@ * processing. is a pointer to the buffer of input * character received by the device. is a pointer to a * pointer of flag bytes which indicate whether a character was - * received with a parity error, etc. + * received with a parity error, etc. Returns the amount of bytes + * received. * * void (*write_wakeup)(struct tty_struct *); * @@ -140,8 +141,8 @@ struct tty_ldisc_ops { /* * The following routines are called from below. */ - void (*receive_buf)(struct tty_struct *, const unsigned char *cp, - char *fp, int count); + unsigned int (*receive_buf)(struct tty_struct *, + const unsigned char *cp, char *fp, int count); void (*write_wakeup)(struct tty_struct *); void (*dcd_change)(struct tty_struct *, unsigned int, struct pps_event_time *); -- cgit v1.2.2 From c29bd8d89c9423aed182dbfdb6527b576a2f3552 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:12 +0200 Subject: Char: nozomi, use GFP_KERNEL for kfifo allocation The allocation was moved to probe function in 9842c38e9176. And we can sleep there. So allocate the 4*8192 bytes as GFP_KERNEL to mitigate the allocation failure. Signed-off-by: Jiri Slaby Tested-by: Gerald Pfeifer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/nozomi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index fd0a98524d5..acaecc17388 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -1431,8 +1431,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, } for (i = PORT_MDM; i < MAX_PORT; i++) { - if (kfifo_alloc(&dc->port[i].fifo_ul, - FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { + if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL, + GFP_KERNEL)) { dev_err(&pdev->dev, "Could not allocate kfifo buffer\n"); ret = -ENOMEM; -- cgit v1.2.2 From 6d742f655efe767dc77a099b57297fa417afc473 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:13 +0200 Subject: Char: nozomi, remove port.count checks Before 33dd474a, these were some kind of protection against race with HUP. They were protected with port->tty_sem at the same time. By that commit, the counting was switched to tty_port's one, but the locking remained the old one. So the count was not protected by any lock anymore. The driver should not test whether it raced with HUP or not anyways. With the new refcounted tty model, it just should proceed as nothing happened because all needed info is still there. In respect to this, let's drop the useless and unprotected tests (tty_port->count is protected by tty_port->lock). Signed-off-by: Jiri Slaby Tested-by: Gerald Pfeifer Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/nozomi.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index acaecc17388..c34d622dace 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -1690,11 +1690,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, mutex_lock(&port->tty_sem); - if (unlikely(!port->port.count)) { - DBG1(" "); - goto exit; - } - rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ @@ -1740,8 +1735,7 @@ static int ntty_write_room(struct tty_struct *tty) if (dc) { mutex_lock(&port->tty_sem); - if (port->port.count) - room = kfifo_avail(&port->fifo_ul); + room = kfifo_avail(&port->fifo_ul); mutex_unlock(&port->tty_sem); } return room; @@ -1889,11 +1883,6 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } - if (unlikely(!port->port.count)) { - dev_err(&dc->pdev->dev, "No tty open?\n"); - goto exit_in_buffer; - } - rval = kfifo_len(&port->fifo_ul); exit_in_buffer: -- cgit v1.2.2 From 7fdc28931176a17ef0bdc5d35742925a155533c4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:14 +0200 Subject: Char: nozomi, remove useless tty_sem tty_sem used to protect tty open count. This was removed in 33dd474a but the lock remained in place. So remove it completely as it protects nothing now. Also this solves Mac's problem with inatomic operation called from atomic context (ppp): BUG: scheduling while atomic: firefox-bin/1992/0x10000800 Modules linked in: ... Pid: 1992, comm: firefox-bin Not tainted 2.6.38 #1 Call Trace: ... [] ? mutex_lock+0xe/0x21 [] ? ntty_write+0x5d/0x192 [nozomi] [] ? __mod_timer.clone.30+0xbe/0xcc [] ? check_preempt_curr+0x60/0x6d [] ? __nf_ct_refresh_acct+0x75/0xbe [] ? ppp_async_push+0xa9/0x3bd [ppp_async] [] ? ppp_async_send+0x34/0x40 [ppp_async] [] ? ppp_push+0x6c/0x4f9 [ppp_generic] ... Signed-off-by: Jiri Slaby Reported-by: Mac Tested-by: Gerald Pfeifer Reviewed-by: Jack Stone Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/nozomi.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index c34d622dace..b1aecc7bb32 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -364,8 +364,6 @@ struct port { u8 toggle_ul; u16 token_dl; - /* mutex to ensure one access patch to this port */ - struct mutex tty_sem; wait_queue_head_t tty_wait; struct async_icount tty_icount; @@ -1474,7 +1472,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, struct device *tty_dev; struct port *port = &dc->port[i]; port->dc = dc; - mutex_init(&port->tty_sem); tty_port_init(&port->port); port->port.ops = &noz_tty_port_ops; tty_dev = tty_register_device(ntty_driver, dc->index_start + i, @@ -1688,8 +1685,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, if (!dc || !port) return -ENODEV; - mutex_lock(&port->tty_sem); - rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ @@ -1714,7 +1709,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, spin_unlock_irqrestore(&dc->spin_mutex, flags); exit: - mutex_unlock(&port->tty_sem); return rval; } @@ -1733,11 +1727,9 @@ static int ntty_write_room(struct tty_struct *tty) int room = 4096; const struct nozomi *dc = get_dc_by_tty(tty); - if (dc) { - mutex_lock(&port->tty_sem); + if (dc) room = kfifo_avail(&port->fifo_ul); - mutex_unlock(&port->tty_sem); - } + return room; } -- cgit v1.2.2 From 0ad7c9af3e1cbb97082062266705d6cb5fb207ee Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:15 +0200 Subject: Char: moxa, fix locking in moxa_write moxa_write can be called from atomic context with irqs disabled (from ppp_async_push). Don't enable interrupts by spin_unlock_bh as this might cause deadlocks in the ppp layer. Instead, use irqsave/irqrestore spin_lock functions. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/moxa.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index a290e9ebafe..6255561dd2a 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1202,14 +1202,15 @@ static int moxa_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct moxa_port *ch = tty->driver_data; + unsigned long flags; int len; if (ch == NULL) return 0; - spin_lock_bh(&moxa_lock); + spin_lock_irqsave(&moxa_lock, flags); len = MoxaPortWriteData(tty, buf, count); - spin_unlock_bh(&moxa_lock); + spin_unlock_irqrestore(&moxa_lock, flags); set_bit(LOWWAIT, &ch->statusflags); return len; -- cgit v1.2.2 From 32ad3a77b256948a326c3f68db6acaad2b6953e7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:16 +0200 Subject: TTY: serial_core, remove invalid test tty->index (named here as line) is set up in initialize_tty_struct. The value is checked in get_tty_driver for the found driver as: if (device < base || device >= base + p->num) continue; *index = device - base; So index/line can never be more than driver->num. Hence remove this test from uart_open. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 55965d5b814..69d00008f7a 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1529,15 +1529,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) BUG_ON(!tty_locked()); pr_debug("uart_open(%d) called\n", line); - /* - * tty->driver->num won't change, so we won't fail here with - * tty->driver_data set to something non-NULL (and therefore - * we won't get caught by uart_close()). - */ - retval = -ENODEV; - if (line >= tty->driver->num) - goto fail; - /* * We take the semaphore inside uart_get to guarantee that we won't * be re-entered while allocating the state structure, or while we -- cgit v1.2.2 From c831cff256c86588976e66bef7897633d534846c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:17 +0200 Subject: TTY: serial_core, remove superfluous set_task_state msleep* is guaranteed to return with TASK_RUNNING task state. And since there is no other set_task_state in the paths of uart_wait_until_sent, we need not to set_task_state to TASK_RUNNING. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 69d00008f7a..db7912cb7ae 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1414,7 +1414,6 @@ static void __uart_wait_until_sent(struct uart_port *port, int timeout) if (time_after(jiffies, expire)) break; } - set_current_state(TASK_RUNNING); /* might not be needed */ } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) -- cgit v1.2.2 From 83c67571b372c4a40023a84e183fdb7fa4e89e48 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 20 Apr 2011 10:43:18 +0200 Subject: TTY: tty_io, annotate locking functions tty_write_lock and tty_write_unlock contain imbalanced locking. But this is intentional, so mark them appropriately by __acquires/__releases. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 3f4ad988543..6556f7452ba 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -962,12 +962,14 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, } void tty_write_unlock(struct tty_struct *tty) + __releases(&tty->atomic_write_lock) { mutex_unlock(&tty->atomic_write_lock); wake_up_interruptible_poll(&tty->write_wait, POLLOUT); } int tty_write_lock(struct tty_struct *tty, int ndelay) + __acquires(&tty->atomic_write_lock) { if (!mutex_trylock(&tty->atomic_write_lock)) { if (ndelay) -- cgit v1.2.2 From df43daaae926c3710eda911ec048808c904572fe Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 22 Apr 2011 22:46:21 +0200 Subject: drivers/tty/moxa.c: Put correct tty value The tty value that should be put is the one that was just gotten by tty_port_tty_get, not the one that is the argument to the enclosing function. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @exists@ local idexpression struct tty_struct *x; expression ra,rr; statement S1,S2; @@ x = tty_port_tty_get(...) ... when != x = rr when any when != tty_kref_put(x,...) when != if (...) { ... tty_kref_put(x,...) ...} ( if(<+...x...+>) S1 else S2 | if(...) { ... when != x = ra when forall when != tty_kref_put(x,...) *return...; } ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/tty/moxa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 6255561dd2a..ba679ce0a77 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -371,7 +371,7 @@ static int moxa_ioctl(struct tty_struct *tty, tmp.cflag = p->cflag; else tmp.cflag = ttyp->termios->c_cflag; - tty_kref_put(tty); + tty_kref_put(ttyp); copy: if (copy_to_user(argm, &tmp, sizeof(tmp))) return -EFAULT; -- cgit v1.2.2 From 0a77c4f9d451a6652f5536548df1b75f4b5b836c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 25 Apr 2011 16:46:49 -0700 Subject: n_gsm: Use print_hex_dump_bytes Use the standard mechanism to print a hex buffer to eliminate empty printf warning. A couple % smaller text and data too. $ size drivers/tty/n_gsm.o* text data bss dec hex filename 23543 312 6376 30231 7617 drivers/tty/n_gsm.o.new 24051 408 6496 30955 78eb drivers/tty/n_gsm.o.old Signed-off-by: Joe Perches Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 6abc7359884..720160acd9d 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -526,19 +526,6 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len) return olen; } -static void hex_packet(const unsigned char *p, int len) -{ - int i; - for (i = 0; i < len; i++) { - if (i && (i % 16) == 0) { - pr_cont("\n"); - pr_debug(""); - } - pr_cont("%02X ", *p++); - } - pr_cont("\n"); -} - /** * gsm_send - send a control frame * @gsm: our GSM mux @@ -685,10 +672,10 @@ static void gsm_data_kick(struct gsm_mux *gsm) len = msg->len + 2; } - if (debug & 4) { - pr_debug("gsm_data_kick:\n"); - hex_packet(gsm->txframe, len); - } + if (debug & 4) + print_hex_dump_bytes("gsm_data_kick: ", + DUMP_PREFIX_OFFSET, + gsm->txframe, len); if (gsm->output(gsm, gsm->txframe + skip_sof, len - skip_sof) < 0) @@ -2091,10 +2078,9 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags); return -ENOSPC; } - if (debug & 4) { - pr_debug("-->%d bytes out\n", len); - hex_packet(data, len); - } + if (debug & 4) + print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET, + data, len); gsm->tty->ops->write(gsm->tty, data, len); return len; } @@ -2148,10 +2134,9 @@ static unsigned int gsmld_receive_buf(struct tty_struct *tty, char buf[64]; char flags; - if (debug & 4) { - pr_debug("Inbytes %dd\n", count); - hex_packet(cp, count); - } + if (debug & 4) + print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET, + cp, count); for (i = count, dp = cp, f = fp; i; i--, dp++) { flags = *f++; -- cgit v1.2.2 From 61ec9016988f5c030e96e3c8a42ee9e11b8517aa Mon Sep 17 00:00:00 2001 From: John Linn Date: Sat, 30 Apr 2011 00:07:43 -0400 Subject: tty/serial: add support for Xilinx PS UART The Xilinx PS Uart is used on the new ARM based SoC. This UART is not compatible with others such that a seperate driver is required. Signed-off-by: John Linn Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 13 + drivers/tty/serial/Makefile | 1 + drivers/tty/serial/xilinx_uartps.c | 1113 ++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 3 + 4 files changed, 1130 insertions(+) create mode 100644 drivers/tty/serial/xilinx_uartps.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 80484af781e..84876ec2ed9 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1612,4 +1612,17 @@ config SERIAL_MXS_AUART_CONSOLE help Enable a MXS AUART port to be the system console. +config SERIAL_XILINX_PS_UART + tristate "Xilinx PS UART support" + select SERIAL_CORE + help + This driver supports the Xilinx PS UART port. + +config SERIAL_XILINX_PS_UART_CONSOLE + bool "Xilinx PS UART console support" + depends on SERIAL_XILINX_PS_UART=y + select SERIAL_CORE_CONSOLE + help + Enable a Xilinx PS UART port to be the system console. + endmenu diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index fee0690ef8e..aafddf15992 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -94,3 +94,4 @@ obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o +obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c new file mode 100644 index 00000000000..19cc1e8149d --- /dev/null +++ b/drivers/tty/serial/xilinx_uartps.c @@ -0,0 +1,1113 @@ +/* + * Xilinx PS UART driver + * + * 2011 (c) Xilinx Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any + * later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define XUARTPS_TTY_NAME "ttyPS" +#define XUARTPS_NAME "xuartps" +#define XUARTPS_MAJOR 0 /* use dynamic node allocation */ +#define XUARTPS_MINOR 0 /* works best with devtmpfs */ +#define XUARTPS_NR_PORTS 2 +#define XUARTPS_FIFO_SIZE 16 /* FIFO size */ +#define XUARTPS_REGISTER_SPACE 0xFFF + +#define xuartps_readl(offset) ioread32(port->membase + offset) +#define xuartps_writel(val, offset) iowrite32(val, port->membase + offset) + +/********************************Register Map********************************/ +/** UART + * + * Register offsets for the UART. + * + */ +#define XUARTPS_CR_OFFSET 0x00 /* Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x04 /* Mode Register [10:0] */ +#define XUARTPS_IER_OFFSET 0x08 /* Interrupt Enable [10:0] */ +#define XUARTPS_IDR_OFFSET 0x0C /* Interrupt Disable [10:0] */ +#define XUARTPS_IMR_OFFSET 0x10 /* Interrupt Mask [10:0] */ +#define XUARTPS_ISR_OFFSET 0x14 /* Interrupt Status [10:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x18 /* Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x1C /* RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x20 /* RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x24 /* Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x28 /* Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x2C /* Channel Status [11:0] */ +#define XUARTPS_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x34 /* Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x38 /* Flow Delay [15:0] */ +#define XUARTPS_IRRX_PWIDTH_OFFSET 0x3C /* IR Minimum Received Pulse + Width [15:0] */ +#define XUARTPS_IRTX_PWIDTH_OFFSET 0x40 /* IR Transmitted pulse + Width [7:0] */ +#define XUARTPS_TXWM_OFFSET 0x44 /* TX FIFO Trigger Level [5:0] */ + +/** Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definitions + */ +#define XUARTPS_CR_STOPBRK 0x00000100 /* Stop TX break */ +#define XUARTPS_CR_STARTBRK 0x00000080 /* Set TX break */ +#define XUARTPS_CR_TX_DIS 0x00000020 /* TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010 /* TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008 /* RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004 /* RX enabled */ +#define XUARTPS_CR_TXRST 0x00000002 /* TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001 /* RX logic reset */ +#define XUARTPS_CR_RST_TO 0x00000040 /* Restart Timeout Counter */ + +/** Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definitions + * + */ +#define XUARTPS_MR_CLKSEL 0x00000001 /* Pre-scalar selection */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200 /* Local loop back mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000 /* Normal mode */ + +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080 /* 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000 /* 1 stop bit */ + +#define XUARTPS_MR_PARITY_NONE 0x00000020 /* No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018 /* Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010 /* Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008 /* Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000 /* Even parity mode */ + +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006 /* 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004 /* 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000 /* 8 bits data */ + +/** Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + */ +#define XUARTPS_IXR_TOUT 0x00000100 /* RX Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080 /* Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040 /* Framing error interrupt */ +#define XUARTPS_IXR_OVERRUN 0x00000020 /* Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010 /* TX FIFO Full interrupt */ +#define XUARTPS_IXR_TXEMPTY 0x00000008 /* TX FIFO empty interrupt */ +#define XUARTPS_ISR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt */ +#define XUARTPS_IXR_RXTRIG 0x00000001 /* RX FIFO trigger interrupt */ +#define XUARTPS_IXR_RXFULL 0x00000004 /* RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ +#define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */ + +/** Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + */ +#define XUARTPS_SR_RXEMPTY 0x00000002 /* RX FIFO empty */ +#define XUARTPS_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ +#define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */ +#define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ + +/** + * xuartps_isr - Interrupt handler + * @irq: Irq number + * @dev_id: Id of the port + * + * Returns IRQHANDLED + **/ +static irqreturn_t xuartps_isr(int irq, void *dev_id) +{ + struct uart_port *port = (struct uart_port *)dev_id; + struct tty_struct *tty; + unsigned long flags; + unsigned int isrstatus, numbytes; + unsigned int data; + char status = TTY_NORMAL; + + /* Get the tty which could be NULL so don't assume it's valid */ + tty = tty_port_tty_get(&port->state->port); + + spin_lock_irqsave(&port->lock, flags); + + /* Read the interrupt status register to determine which + * interrupt(s) is/are active. + */ + isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET); + + /* drop byte with parity error if IGNPAR specified */ + if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY) + isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT); + + isrstatus &= port->read_status_mask; + isrstatus &= ~port->ignore_status_mask; + + if ((isrstatus & XUARTPS_IXR_TOUT) || + (isrstatus & XUARTPS_IXR_RXTRIG)) { + /* Receive Timeout Interrupt */ + while ((xuartps_readl(XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { + data = xuartps_readl(XUARTPS_FIFO_OFFSET); + port->icount.rx++; + + if (isrstatus & XUARTPS_IXR_PARITY) { + port->icount.parity++; + status = TTY_PARITY; + } else if (isrstatus & XUARTPS_IXR_FRAMING) { + port->icount.frame++; + status = TTY_FRAME; + } else if (isrstatus & XUARTPS_IXR_OVERRUN) + port->icount.overrun++; + + if (tty) + uart_insert_char(port, isrstatus, + XUARTPS_IXR_OVERRUN, data, + status); + } + spin_unlock(&port->lock); + if (tty) + tty_flip_buffer_push(tty); + spin_lock(&port->lock); + } + + /* Dispatch an appropriate handler */ + if ((isrstatus & XUARTPS_IXR_TXEMPTY) == XUARTPS_IXR_TXEMPTY) { + if (uart_circ_empty(&port->state->xmit)) { + xuartps_writel(XUARTPS_IXR_TXEMPTY, + XUARTPS_IDR_OFFSET); + } else { + numbytes = port->fifosize; + /* Break if no more data available in the UART buffer */ + while (numbytes--) { + if (uart_circ_empty(&port->state->xmit)) + break; + /* Get the data from the UART circular buffer + * and write it to the xuartps's TX_FIFO + * register. + */ + xuartps_writel( + port->state->xmit.buf[port->state->xmit. + tail], XUARTPS_FIFO_OFFSET); + + port->icount.tx++; + + /* Adjust the tail of the UART buffer and wrap + * the buffer if it reaches limit. + */ + port->state->xmit.tail = + (port->state->xmit.tail + 1) & \ + (UART_XMIT_SIZE - 1); + } + + if (uart_circ_chars_pending( + &port->state->xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + } + } + + xuartps_writel(isrstatus, XUARTPS_ISR_OFFSET); + + /* be sure to release the lock and tty before leaving */ + spin_unlock_irqrestore(&port->lock, flags); + tty_kref_put(tty); + + return IRQ_HANDLED; +} + +/** + * xuartps_set_baud_rate - Calculate and set the baud rate + * @port: Handle to the uart port structure + * @baud: Baud rate to set + * + * Returns baud rate, requested baud when possible, or actual baud when there + * was too much error + **/ +static unsigned int xuartps_set_baud_rate(struct uart_port *port, + unsigned int baud) +{ + unsigned int sel_clk; + unsigned int calc_baud = 0; + unsigned int brgr_val, brdiv_val; + unsigned int bauderror; + + /* Formula to obtain baud rate is + * baud_tx/rx rate = sel_clk/CD * (BDIV + 1) + * input_clk = (Uart User Defined Clock or Apb Clock) + * depends on UCLKEN in MR Reg + * sel_clk = input_clk or input_clk/8; + * depends on CLKS in MR reg + * CD and BDIV depends on values in + * baud rate generate register + * baud rate clock divisor register + */ + sel_clk = port->uartclk; + if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL) + sel_clk = sel_clk / 8; + + /* Find the best values for baud generation */ + for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) { + + brgr_val = sel_clk / (baud * (brdiv_val + 1)); + if (brgr_val < 2 || brgr_val > 65535) + continue; + + calc_baud = sel_clk / (brgr_val * (brdiv_val + 1)); + + if (baud > calc_baud) + bauderror = baud - calc_baud; + else + bauderror = calc_baud - baud; + + /* use the values when percent error is acceptable */ + if (((bauderror * 100) / baud) < 3) { + calc_baud = baud; + break; + } + } + + /* Set the values for the new baud rate */ + xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET); + xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET); + + return calc_baud; +} + +/*----------------------Uart Operations---------------------------*/ + +/** + * xuartps_start_tx - Start transmitting bytes + * @port: Handle to the uart port structure + * + **/ +static void xuartps_start_tx(struct uart_port *port) +{ + unsigned int status, numbytes = port->fifosize; + + if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port)) + return; + + status = xuartps_readl(XUARTPS_CR_OFFSET); + /* Set the TX enable bit and clear the TX disable bit to enable the + * transmitter. + */ + xuartps_writel((status & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN, + XUARTPS_CR_OFFSET); + + while (numbytes-- && ((xuartps_readl(XUARTPS_SR_OFFSET) + & XUARTPS_SR_TXFULL)) != XUARTPS_SR_TXFULL) { + + /* Break if no more data available in the UART buffer */ + if (uart_circ_empty(&port->state->xmit)) + break; + + /* Get the data from the UART circular buffer and + * write it to the xuartps's TX_FIFO register. + */ + xuartps_writel( + port->state->xmit.buf[port->state->xmit.tail], + XUARTPS_FIFO_OFFSET); + port->icount.tx++; + + /* Adjust the tail of the UART buffer and wrap + * the buffer if it reaches limit. + */ + port->state->xmit.tail = (port->state->xmit.tail + 1) & + (UART_XMIT_SIZE - 1); + } + + /* Enable the TX Empty interrupt */ + xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET); + + if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +/** + * xuartps_stop_tx - Stop TX + * @port: Handle to the uart port structure + * + **/ +static void xuartps_stop_tx(struct uart_port *port) +{ + unsigned int regval; + + regval = xuartps_readl(XUARTPS_CR_OFFSET); + regval |= XUARTPS_CR_TX_DIS; + /* Disable the transmitter */ + xuartps_writel(regval, XUARTPS_CR_OFFSET); +} + +/** + * xuartps_stop_rx - Stop RX + * @port: Handle to the uart port structure + * + **/ +static void xuartps_stop_rx(struct uart_port *port) +{ + unsigned int regval; + + regval = xuartps_readl(XUARTPS_CR_OFFSET); + regval |= XUARTPS_CR_RX_DIS; + /* Disable the receiver */ + xuartps_writel(regval, XUARTPS_CR_OFFSET); +} + +/** + * xuartps_tx_empty - Check whether TX is empty + * @port: Handle to the uart port structure + * + * Returns TIOCSER_TEMT on success, 0 otherwise + **/ +static unsigned int xuartps_tx_empty(struct uart_port *port) +{ + unsigned int status; + + status = xuartps_readl(XUARTPS_ISR_OFFSET) & XUARTPS_IXR_TXEMPTY; + return status ? TIOCSER_TEMT : 0; +} + +/** + * xuartps_break_ctl - Based on the input ctl we have to start or stop + * transmitting char breaks + * @port: Handle to the uart port structure + * @ctl: Value based on which start or stop decision is taken + * + **/ +static void xuartps_break_ctl(struct uart_port *port, int ctl) +{ + unsigned int status; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + status = xuartps_readl(XUARTPS_CR_OFFSET); + + if (ctl == -1) + xuartps_writel(XUARTPS_CR_STARTBRK | status, + XUARTPS_CR_OFFSET); + else { + if ((status & XUARTPS_CR_STOPBRK) == 0) + xuartps_writel(XUARTPS_CR_STOPBRK | status, + XUARTPS_CR_OFFSET); + } + spin_unlock_irqrestore(&port->lock, flags); +} + +/** + * xuartps_set_termios - termios operations, handling data length, parity, + * stop bits, flow control, baud rate + * @port: Handle to the uart port structure + * @termios: Handle to the input termios structure + * @old: Values of the previously saved termios structure + * + **/ +static void xuartps_set_termios(struct uart_port *port, + struct ktermios *termios, struct ktermios *old) +{ + unsigned int cval = 0; + unsigned int baud; + unsigned long flags; + unsigned int ctrl_reg, mode_reg; + + spin_lock_irqsave(&port->lock, flags); + + /* Empty the receive FIFO 1st before making changes */ + while ((xuartps_readl(XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { + xuartps_readl(XUARTPS_FIFO_OFFSET); + } + + /* Disable the TX and RX to set baud rate */ + xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | + (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), + XUARTPS_CR_OFFSET); + + /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ + baud = uart_get_baud_rate(port, termios, old, 0, 10000000); + baud = xuartps_set_baud_rate(port, baud); + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, baud); + + /* Set TX/RX Reset */ + xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | + (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), + XUARTPS_CR_OFFSET); + + ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); + + /* Clear the RX disable and TX disable bits and then set the TX enable + * bit and RX enable bit to enable the transmitter and receiver. + */ + xuartps_writel( + (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) + | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), + XUARTPS_CR_OFFSET); + + xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); + + port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | + XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; + port->ignore_status_mask = 0; + + if (termios->c_iflag & INPCK) + port->read_status_mask |= XUARTPS_IXR_PARITY | + XUARTPS_IXR_FRAMING; + + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= XUARTPS_IXR_PARITY | + XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; + + /* ignore all characters if CREAD is not set */ + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= XUARTPS_IXR_RXTRIG | + XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | + XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; + + mode_reg = xuartps_readl(XUARTPS_MR_OFFSET); + + /* Handling Data Size */ + switch (termios->c_cflag & CSIZE) { + case CS6: + cval |= XUARTPS_MR_CHARLEN_6_BIT; + break; + case CS7: + cval |= XUARTPS_MR_CHARLEN_7_BIT; + break; + default: + case CS8: + cval |= XUARTPS_MR_CHARLEN_8_BIT; + termios->c_cflag &= ~CSIZE; + termios->c_cflag |= CS8; + break; + } + + /* Handling Parity and Stop Bits length */ + if (termios->c_cflag & CSTOPB) + cval |= XUARTPS_MR_STOPMODE_2_BIT; /* 2 STOP bits */ + else + cval |= XUARTPS_MR_STOPMODE_1_BIT; /* 1 STOP bit */ + + if (termios->c_cflag & PARENB) { + /* Mark or Space parity */ + if (termios->c_cflag & CMSPAR) { + if (termios->c_cflag & PARODD) + cval |= XUARTPS_MR_PARITY_MARK; + else + cval |= XUARTPS_MR_PARITY_SPACE; + } else if (termios->c_cflag & PARODD) + cval |= XUARTPS_MR_PARITY_ODD; + else + cval |= XUARTPS_MR_PARITY_EVEN; + } else + cval |= XUARTPS_MR_PARITY_NONE; + xuartps_writel(cval , XUARTPS_MR_OFFSET); + + spin_unlock_irqrestore(&port->lock, flags); +} + +/** + * xuartps_startup - Called when an application opens a xuartps port + * @port: Handle to the uart port structure + * + * Returns 0 on success, negative error otherwise + **/ +static int xuartps_startup(struct uart_port *port) +{ + unsigned int retval = 0, status = 0; + + retval = request_irq(port->irq, xuartps_isr, 0, XUARTPS_NAME, + (void *)port); + if (retval) + return retval; + + /* Disable the TX and RX */ + xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS, + XUARTPS_CR_OFFSET); + + /* Set the Control Register with TX/RX Enable, TX/RX Reset, + * no break chars. + */ + xuartps_writel(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST, + XUARTPS_CR_OFFSET); + + status = xuartps_readl(XUARTPS_CR_OFFSET); + + /* Clear the RX disable and TX disable bits and then set the TX enable + * bit and RX enable bit to enable the transmitter and receiver. + */ + xuartps_writel((status & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) + | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN | + XUARTPS_CR_STOPBRK), XUARTPS_CR_OFFSET); + + /* Set the Mode Register with normal mode,8 data bits,1 stop bit, + * no parity. + */ + xuartps_writel(XUARTPS_MR_CHMODE_NORM | XUARTPS_MR_STOPMODE_1_BIT + | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT, + XUARTPS_MR_OFFSET); + + /* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */ + xuartps_writel(14, XUARTPS_RXWM_OFFSET); + + /* Receive Timeout register is enabled with value of 10 */ + xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); + + + /* Set the Interrupt Registers with desired interrupts */ + xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | + XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN | + XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET); + xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | + XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN | + XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET); + + return retval; +} + +/** + * xuartps_shutdown - Called when an application closes a xuartps port + * @port: Handle to the uart port structure + * + **/ +static void xuartps_shutdown(struct uart_port *port) +{ + int status; + + /* Disable interrupts */ + status = xuartps_readl(XUARTPS_IMR_OFFSET); + xuartps_writel(status, XUARTPS_IDR_OFFSET); + + /* Disable the TX and RX */ + xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS, + XUARTPS_CR_OFFSET); + free_irq(port->irq, port); +} + +/** + * xuartps_type - Set UART type to xuartps port + * @port: Handle to the uart port structure + * + * Returns string on success, NULL otherwise + **/ +static const char *xuartps_type(struct uart_port *port) +{ + return port->type == PORT_XUARTPS ? XUARTPS_NAME : NULL; +} + +/** + * xuartps_verify_port - Verify the port params + * @port: Handle to the uart port structure + * @ser: Handle to the structure whose members are compared + * + * Returns 0 if success otherwise -EINVAL + **/ +static int xuartps_verify_port(struct uart_port *port, + struct serial_struct *ser) +{ + if (ser->type != PORT_UNKNOWN && ser->type != PORT_XUARTPS) + return -EINVAL; + if (port->irq != ser->irq) + return -EINVAL; + if (ser->io_type != UPIO_MEM) + return -EINVAL; + if (port->iobase != ser->port) + return -EINVAL; + if (ser->hub6 != 0) + return -EINVAL; + return 0; +} + +/** + * xuartps_request_port - Claim the memory region attached to xuartps port, + * called when the driver adds a xuartps port via + * uart_add_one_port() + * @port: Handle to the uart port structure + * + * Returns 0, -ENOMEM if request fails + **/ +static int xuartps_request_port(struct uart_port *port) +{ + if (!request_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE, + XUARTPS_NAME)) { + return -ENOMEM; + } + + port->membase = ioremap(port->mapbase, XUARTPS_REGISTER_SPACE); + if (!port->membase) { + dev_err(port->dev, "Unable to map registers\n"); + release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE); + return -ENOMEM; + } + return 0; +} + +/** + * xuartps_release_port - Release the memory region attached to a xuartps + * port, called when the driver removes a xuartps + * port via uart_remove_one_port(). + * @port: Handle to the uart port structure + * + **/ +static void xuartps_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE); + iounmap(port->membase); + port->membase = NULL; +} + +/** + * xuartps_config_port - Configure xuartps, called when the driver adds a + * xuartps port + * @port: Handle to the uart port structure + * @flags: If any + * + **/ +static void xuartps_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE && xuartps_request_port(port) == 0) + port->type = PORT_XUARTPS; +} + +/** + * xuartps_get_mctrl - Get the modem control state + * + * @port: Handle to the uart port structure + * + * Returns the modem control state + * + **/ +static unsigned int xuartps_get_mctrl(struct uart_port *port) +{ + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; +} + +static void xuartps_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* N/A */ +} + +static void xuartps_enable_ms(struct uart_port *port) +{ + /* N/A */ +} + +/** The UART operations structure + */ +static struct uart_ops xuartps_ops = { + .set_mctrl = xuartps_set_mctrl, + .get_mctrl = xuartps_get_mctrl, + .enable_ms = xuartps_enable_ms, + + .start_tx = xuartps_start_tx, /* Start transmitting */ + .stop_tx = xuartps_stop_tx, /* Stop transmission */ + .stop_rx = xuartps_stop_rx, /* Stop reception */ + .tx_empty = xuartps_tx_empty, /* Transmitter busy? */ + .break_ctl = xuartps_break_ctl, /* Start/stop + * transmitting break + */ + .set_termios = xuartps_set_termios, /* Set termios */ + .startup = xuartps_startup, /* App opens xuartps */ + .shutdown = xuartps_shutdown, /* App closes xuartps */ + .type = xuartps_type, /* Set UART type */ + .verify_port = xuartps_verify_port, /* Verification of port + * params + */ + .request_port = xuartps_request_port, /* Claim resources + * associated with a + * xuartps port + */ + .release_port = xuartps_release_port, /* Release resources + * associated with a + * xuartps port + */ + .config_port = xuartps_config_port, /* Configure when driver + * adds a xuartps port + */ +}; + +static struct uart_port xuartps_port[2]; + +/** + * xuartps_get_port - Configure the port from the platform device resource + * info + * + * Returns a pointer to a uart_port or NULL for failure + **/ +static struct uart_port *xuartps_get_port(void) +{ + struct uart_port *port; + int id; + + /* Find the next unused port */ + for (id = 0; id < XUARTPS_NR_PORTS; id++) + if (xuartps_port[id].mapbase == 0) + break; + + if (id >= XUARTPS_NR_PORTS) + return NULL; + + port = &xuartps_port[id]; + + /* At this point, we've got an empty uart_port struct, initialize it */ + spin_lock_init(&port->lock); + port->membase = NULL; + port->iobase = 1; /* mark port in use */ + port->irq = 0; + port->type = PORT_UNKNOWN; + port->iotype = UPIO_MEM32; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &xuartps_ops; + port->fifosize = XUARTPS_FIFO_SIZE; + port->line = id; + port->dev = NULL; + return port; +} + +/*-----------------------Console driver operations--------------------------*/ + +#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE +/** + * xuartps_console_wait_tx - Wait for the TX to be full + * @port: Handle to the uart port structure + * + **/ +static void xuartps_console_wait_tx(struct uart_port *port) +{ + while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY) + != XUARTPS_SR_TXEMPTY) + barrier(); +} + +/** + * xuartps_console_putchar - write the character to the FIFO buffer + * @port: Handle to the uart port structure + * @ch: Character to be written + * + **/ +static void xuartps_console_putchar(struct uart_port *port, int ch) +{ + xuartps_console_wait_tx(port); + xuartps_writel(ch, XUARTPS_FIFO_OFFSET); +} + +/** + * xuartps_console_write - perform write operation + * @port: Handle to the uart port structure + * @s: Pointer to character array + * @count: No of characters + **/ +static void xuartps_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct uart_port *port = &xuartps_port[co->index]; + unsigned long flags; + unsigned int imr; + int locked = 1; + + if (oops_in_progress) + locked = spin_trylock_irqsave(&port->lock, flags); + else + spin_lock_irqsave(&port->lock, flags); + + /* save and disable interrupt */ + imr = xuartps_readl(XUARTPS_IMR_OFFSET); + xuartps_writel(imr, XUARTPS_IDR_OFFSET); + + uart_console_write(port, s, count, xuartps_console_putchar); + xuartps_console_wait_tx(port); + + /* restore interrupt state, it seems like there may be a h/w bug + * in that the interrupt enable register should not need to be + * written based on the data sheet + */ + xuartps_writel(~imr, XUARTPS_IDR_OFFSET); + xuartps_writel(imr, XUARTPS_IER_OFFSET); + + if (locked) + spin_unlock_irqrestore(&port->lock, flags); +} + +/** + * xuartps_console_setup - Initialize the uart to default config + * @co: Console handle + * @options: Initial settings of uart + * + * Returns 0, -ENODEV if no device + **/ +static int __init xuartps_console_setup(struct console *co, char *options) +{ + struct uart_port *port = &xuartps_port[co->index]; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index < 0 || co->index >= XUARTPS_NR_PORTS) + return -EINVAL; + + if (!port->mapbase) { + pr_debug("console on ttyPS%i not present\n", co->index); + return -ENODEV; + } + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct uart_driver xuartps_uart_driver; + +static struct console xuartps_console = { + .name = XUARTPS_TTY_NAME, + .write = xuartps_console_write, + .device = uart_console_device, + .setup = xuartps_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */ + .data = &xuartps_uart_driver, +}; + +/** + * xuartps_console_init - Initialization call + * + * Returns 0 on success, negative error otherwise + **/ +static int __init xuartps_console_init(void) +{ + register_console(&xuartps_console); + return 0; +} + +console_initcall(xuartps_console_init); + +#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ + +/** Structure Definitions + */ +static struct uart_driver xuartps_uart_driver = { + .owner = THIS_MODULE, /* Owner */ + .driver_name = XUARTPS_NAME, /* Driver name */ + .dev_name = XUARTPS_TTY_NAME, /* Node name */ + .major = XUARTPS_MAJOR, /* Major number */ + .minor = XUARTPS_MINOR, /* Minor number */ + .nr = XUARTPS_NR_PORTS, /* Number of UART ports */ +#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE + .cons = &xuartps_console, /* Console */ +#endif +}; + +/* --------------------------------------------------------------------- + * Platform bus binding + */ +/** + * xuartps_probe - Platform driver probe + * @pdev: Pointer to the platform device structure + * + * Returns 0 on success, negative error otherwise + **/ +static int __devinit xuartps_probe(struct platform_device *pdev) +{ + int rc; + struct uart_port *port; + struct resource *res, *res2; + int clk = 0; + +#ifdef CONFIG_OF + const unsigned int *prop; + + prop = of_get_property(pdev->dev.of_node, "clock", NULL); + if (prop) + clk = be32_to_cpup(prop); +#else + clk = *((unsigned int *)(pdev->dev.platform_data)); +#endif + if (!clk) { + dev_err(&pdev->dev, "no clock specified\n"); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res2) + return -ENODEV; + + /* Initialize the port structure */ + port = xuartps_get_port(); + + if (!port) { + dev_err(&pdev->dev, "Cannot get uart_port structure\n"); + return -ENODEV; + } else { + /* Register the port. + * This function also registers this device with the tty layer + * and triggers invocation of the config_port() entry point. + */ + port->mapbase = res->start; + port->irq = res2->start; + port->dev = &pdev->dev; + port->uartclk = clk; + dev_set_drvdata(&pdev->dev, port); + rc = uart_add_one_port(&xuartps_uart_driver, port); + if (rc) { + dev_err(&pdev->dev, + "uart_add_one_port() failed; err=%i\n", rc); + dev_set_drvdata(&pdev->dev, NULL); + return rc; + } + return 0; + } +} + +/** + * xuartps_remove - called when the platform driver is unregistered + * @pdev: Pointer to the platform device structure + * + * Returns 0 on success, negative error otherwise + **/ +static int __devexit xuartps_remove(struct platform_device *pdev) +{ + struct uart_port *port = dev_get_drvdata(&pdev->dev); + int rc = 0; + + /* Remove the xuartps port from the serial core */ + if (port) { + rc = uart_remove_one_port(&xuartps_uart_driver, port); + dev_set_drvdata(&pdev->dev, NULL); + port->mapbase = 0; + } + return rc; +} + +/** + * xuartps_suspend - suspend event + * @pdev: Pointer to the platform device structure + * @state: State of the device + * + * Returns 0 + **/ +static int xuartps_suspend(struct platform_device *pdev, pm_message_t state) +{ + /* Call the API provided in serial_core.c file which handles + * the suspend. + */ + uart_suspend_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); + return 0; +} + +/** + * xuartps_resume - Resume after a previous suspend + * @pdev: Pointer to the platform device structure + * + * Returns 0 + **/ +static int xuartps_resume(struct platform_device *pdev) +{ + uart_resume_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); + return 0; +} + +/* Match table for of_platform binding */ + +#ifdef CONFIG_OF +static struct of_device_id xuartps_of_match[] __devinitdata = { + { .compatible = "xlnx,xuartps", }, + {} +}; +MODULE_DEVICE_TABLE(of, xuartps_of_match); +#else +#define xuartps_of_match NULL +#endif + +static struct platform_driver xuartps_platform_driver = { + .probe = xuartps_probe, /* Probe method */ + .remove = __exit_p(xuartps_remove), /* Detach method */ + .suspend = xuartps_suspend, /* Suspend */ + .resume = xuartps_resume, /* Resume after a suspend */ + .driver = { + .owner = THIS_MODULE, + .name = XUARTPS_NAME, /* Driver name */ + .of_match_table = xuartps_of_match, + }, +}; + +/* --------------------------------------------------------------------- + * Module Init and Exit + */ +/** + * xuartps_init - Initial driver registration call + * + * Returns whether the registration was successful or not + **/ +static int __init xuartps_init(void) +{ + int retval = 0; + + /* Register the xuartps driver with the serial core */ + retval = uart_register_driver(&xuartps_uart_driver); + if (retval) + return retval; + + /* Register the platform driver */ + retval = platform_driver_register(&xuartps_platform_driver); + if (retval) + uart_unregister_driver(&xuartps_uart_driver); + + return retval; +} + +/** + * xuartps_exit - Driver unregistration call + **/ +static void __exit xuartps_exit(void) +{ + /* The order of unregistration is important. Unregister the + * UART driver before the platform driver crashes the system. + */ + + /* Unregister the platform driver */ + platform_driver_unregister(&xuartps_platform_driver); + + /* Unregister the xuartps driver */ + uart_unregister_driver(&xuartps_uart_driver); +} + +module_init(xuartps_init); +module_exit(xuartps_exit); + +MODULE_DESCRIPTION("Driver for PS UART"); +MODULE_AUTHOR("Xilinx Inc."); +MODULE_LICENSE("GPL"); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 758c5b0c6fd..95d479ba514 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -202,6 +202,9 @@ /* VIA VT8500 SoC */ #define PORT_VT8500 97 +/* Xilinx PSS UART */ +#define PORT_XUARTPS 98 + #ifdef __KERNEL__ #include -- cgit v1.2.2 From 868d1721a2200244a4555193d4adc1133cfb3978 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 4 May 2011 10:18:42 +0100 Subject: parport: Use request_muxed_region for IT87 probe and lock This is needed as part of making the various IT87 drivers actually co-exist politely with each other, and with other superio devices that may be muxed on 0x2E/0x2F. It can be applied before or after the other patches by Nat Gurumoorthy without problem. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index a3755ffc03d..d3c06653c47 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -1621,7 +1621,7 @@ static void __devinit detect_and_report_it87(void) u8 origval, r; if (verbose_probing) printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); - if (!request_region(0x2e, 2, __func__)) + if (!request_muxed_region(0x2e, 2, __func__)) return; origval = inb(0x2e); /* Save original value */ outb(0x87, 0x2e); -- cgit v1.2.2 From 177c2cbf7dc4f6599efa6cd2b514381784f47634 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Mon, 9 May 2011 17:25:20 +0900 Subject: pch_uart: Support new device ML7223 IOH Support new device OKI SEMICONDUCTOR ML7223 IOH(Input/Output Hub). The ML7223 IOH is for MP(Media Phone) use. The ML7223 is companion chip for Intel Atom E6xx series. The ML7223 is completely compatible for Intel EG20T PCH. Signed-off-by: Tomoya MORINAGA Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 12 +++++++----- drivers/tty/serial/pch_uart.c | 8 ++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 84876ec2ed9..2f96ce9924b 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1577,7 +1577,7 @@ config SERIAL_IFX6X60 Support for the IFX6x60 modem devices on Intel MID platforms. config SERIAL_PCH_UART - tristate "Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH" + tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART" depends on PCI select SERIAL_CORE help @@ -1585,10 +1585,12 @@ config SERIAL_PCH_UART which is an IOH(Input/Output Hub) for x86 embedded processor. Enabling PCH_DMA, this PCH UART works as DMA mode. - This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/ - Output Hub) which is for IVI(In-Vehicle Infotainment) use. - ML7213 is companion chip for Intel Atom E6xx series. - ML7213 is completely compatible for Intel EG20T PCH. + This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ + Output Hub), ML7213 and ML7223. + ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is + for MP(Media Phone) use. + ML7213/ML7223 is companion chip for Intel Atom E6xx series. + ML7213/ML7223 is completely compatible for Intel EG20T PCH. config SERIAL_MSM_SMD bool "Enable tty device interface for some SMD ports" diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 26403b8e4b9..c63d0d152af 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -253,6 +253,8 @@ enum pch_uart_num_t { pch_ml7213_uart0, pch_ml7213_uart1, pch_ml7213_uart2, + pch_ml7223_uart0, + pch_ml7223_uart1, }; static struct pch_uart_driver_data drv_dat[] = { @@ -263,6 +265,8 @@ static struct pch_uart_driver_data drv_dat[] = { [pch_ml7213_uart0] = {PCH_UART_8LINE, 0}, [pch_ml7213_uart1] = {PCH_UART_2LINE, 1}, [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, + [pch_ml7223_uart0] = {PCH_UART_8LINE, 0}, + [pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, }; static unsigned int default_baud = 9600; @@ -1534,6 +1538,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { .driver_data = pch_ml7213_uart1}, {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029), .driver_data = pch_ml7213_uart2}, + {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800C), + .driver_data = pch_ml7223_uart0}, + {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D), + .driver_data = pch_ml7223_uart1}, {0,}, }; -- cgit v1.2.2 From ed0bd2333cffc3d856db9beb829543c1dfc00982 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 May 2011 16:05:44 +0200 Subject: ASoC: Update cx20442 for TTY API change receive_buf() was recently changed to return the number of bytes received but the cx20442 driver wasn't updated to match the new API. I don't have any hardware but since we don't actually appears to be listening to the data at all just report that we accepted all the data that was offered to us. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/cx20442.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 0bb424af956..64f863d51ac 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -274,14 +274,14 @@ static int v253_hangup(struct tty_struct *tty) } /* Line discipline .receive_buf() */ -static void v253_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) +static unsigned int v253_receive(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { struct snd_soc_codec *codec = tty->disc_data; struct cx20442_priv *cx20442; if (!codec) - return; + return count; cx20442 = snd_soc_codec_get_drvdata(codec); @@ -293,6 +293,8 @@ static void v253_receive(struct tty_struct *tty, codec->hw_write = (hw_write_t)tty->ops->write; codec->card->pop_time = 1; } + + return count; } /* Line discipline .write_wakeup() */ -- cgit v1.2.2 From aa273ae52118265c5cb0f7026a7f032c765c8b67 Mon Sep 17 00:00:00 2001 From: Scott Kilau Date: Wed, 11 May 2011 15:41:59 -0500 Subject: 8250_pci: Add support for the Digi/IBM PCIe 2-port Adapter Add support to the 8250 PCI serial driver for the Digi/IBM PCIe 2-port Async EIA-232 Adapter. Oxford Semiconductor produces a 2/4/8 port UART (OXPCIe952/OXPCIe954/OXPCIe958) chip called the Tornado, that can be used to create a very simple serial board product. The kernel sources currently have just 2 vendors using this chip, which is Oxford and Mainpipe. This new Digi/IBM serial product now uses it as well. Rather than create a long running comment of vendors using the chip, the one changed comment in the patch below now just lists "For Oxford Semiconductor Tornado based devices" to be a more generic comment for all vendors that end up using the Oxford Tornado chip. Cc: Michael Reed Signed-off-by: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250_pci.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 98311ac815c..762db97aecd 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -1010,6 +1010,7 @@ static int skip_tx_en_setup(struct serial_private *priv, #define PCI_DEVICE_ID_TITAN_200EI 0xA016 #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 +#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1410,7 +1411,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_default_setup, }, /* - * For Oxford Semiconductor and Mainpine + * For Oxford Semiconductor Tornado based devices */ { .vendor = PCI_VENDOR_ID_OXSEMI, @@ -1428,6 +1429,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .init = pci_oxsemi_tornado_init, .setup = pci_default_setup, }, + { + .vendor = PCI_VENDOR_ID_DIGI, + .device = PCIE_DEVICE_ID_NEO_2_OX_IBM, + .subvendor = PCI_SUBVENDOR_ID_IBM, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, + .setup = pci_default_setup, + }, /* * Default "match everything" terminator entry */ @@ -3073,6 +3082,14 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, pbn_oxsemi_8_4000000 }, + + /* + * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado + */ + { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM, + PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + /* * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, * from skokodyn@yahoo.com -- cgit v1.2.2 From 275640b0d8f0ef8c493d7b6613a23d427929b5db Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 May 2011 13:12:36 +0900 Subject: pch_phub: Support new device ML7223 Support new device OKI SEMICONDUCTOR ML7223 IOH(Input/Output Hub). The ML7223 IOH is for MP(Media Phone) use. The ML7223 is companion chip for Intel Atom E6xx series. The ML7223 is completely compatible for Intel EG20T PCH. Signed-off-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 12 ++-- drivers/misc/pch_phub.c | 153 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 29 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4e007c6a4b4..915c31ef84c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -459,7 +459,7 @@ config BMP085 module will be called bmp085. config PCH_PHUB - tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213" + tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB" depends on PCI help This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of @@ -467,10 +467,12 @@ config PCH_PHUB processor. The Topcliff has MAC address and Option ROM data in SROM. This driver can access MAC address and Option ROM data in SROM. - This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is - for IVI(In-Vehicle Infotainment) use. - ML7213 is companion chip for Intel Atom E6xx series. - ML7213 is completely compatible for Intel EG20T PCH. + This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ + Output Hub), ML7213 and ML7223. + ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is + for MP(Media Phone) use. + ML7213/ML7223 is companion chip for Intel Atom E6xx series. + ML7213/ML7223 is completely compatible for Intel EG20T PCH. To compile this driver as a module, choose M here: the module will be called pch_phub. diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index a19cb710a24..5fe79df4483 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -34,12 +34,18 @@ #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ -#define PCH_PHUB_MAC_START_ADDR 0x20C /* MAC data area start address offset */ -#define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset +#define PCH_PHUB_MAC_START_ADDR_EG20T 0x14 /* MAC data area start address + offset */ +#define PCH_PHUB_MAC_START_ADDR_ML7223 0x20C /* MAC data area start address + offset */ +#define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset (Intel EG20T PCH)*/ #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address offset(OKI SEMICONDUCTOR ML7213) */ +#define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address + offset(OKI SEMICONDUCTOR ML7223) + */ /* MAX number of INT_REDUCE_CONTROL registers */ #define MAX_NUM_INT_REDUCE_CONTROL_REG 128 @@ -63,6 +69,10 @@ #define PCI_VENDOR_ID_ROHM 0x10db #define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A +/* Macros for ML7223 */ +#define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */ +#define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */ + /* SROM ACCESS Macro */ #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) @@ -100,6 +110,9 @@ * @clkcfg_reg: CLK CFG register val * @pch_phub_base_address: Register base address * @pch_phub_extrom_base_address: external rom base address + * @pch_mac_start_address: MAC address area start address + * @pch_opt_rom_start_address: Option ROM start address + * @ioh_type: Save IOH type */ struct pch_phub_reg { u32 phub_id_reg; @@ -117,6 +130,9 @@ struct pch_phub_reg { u32 clkcfg_reg; void __iomem *pch_phub_base_address; void __iomem *pch_phub_extrom_base_address; + u32 pch_mac_start_address; + u32 pch_opt_rom_start_address; + int ioh_type; }; /* SROM SPEC for MAC address assignment offset */ @@ -319,7 +335,7 @@ static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip, { unsigned int mem_addr; - mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + + mem_addr = chip->pch_mac_start_address + pch_phub_mac_offset[offset_address]; pch_phub_read_serial_rom(chip, mem_addr, data); @@ -336,7 +352,7 @@ static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip, int retval; unsigned int mem_addr; - mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + + mem_addr = chip->pch_mac_start_address + pch_phub_mac_offset[offset_address]; retval = pch_phub_write_serial_rom(chip, mem_addr, data); @@ -384,6 +400,48 @@ static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip) return retval; } +/* pch_phub_gbe_serial_rom_conf_mp - makes SerialROM header format configuration + * for Gigabit Ethernet MAC address + */ +static int pch_phub_gbe_serial_rom_conf_mp(struct pch_phub_reg *chip) +{ + int retval; + u32 offset_addr; + + offset_addr = 0x200; + retval = pch_phub_write_serial_rom(chip, 0x03 + offset_addr, 0xbc); + retval |= pch_phub_write_serial_rom(chip, 0x02 + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x01 + offset_addr, 0x40); + retval |= pch_phub_write_serial_rom(chip, 0x00 + offset_addr, 0x02); + + retval |= pch_phub_write_serial_rom(chip, 0x07 + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x06 + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x05 + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x04 + offset_addr, 0x80); + + retval |= pch_phub_write_serial_rom(chip, 0x0b + offset_addr, 0xbc); + retval |= pch_phub_write_serial_rom(chip, 0x0a + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x09 + offset_addr, 0x40); + retval |= pch_phub_write_serial_rom(chip, 0x08 + offset_addr, 0x18); + + retval |= pch_phub_write_serial_rom(chip, 0x13 + offset_addr, 0xbc); + retval |= pch_phub_write_serial_rom(chip, 0x12 + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x11 + offset_addr, 0x40); + retval |= pch_phub_write_serial_rom(chip, 0x10 + offset_addr, 0x19); + + retval |= pch_phub_write_serial_rom(chip, 0x1b + offset_addr, 0xbc); + retval |= pch_phub_write_serial_rom(chip, 0x1a + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x19 + offset_addr, 0x40); + retval |= pch_phub_write_serial_rom(chip, 0x18 + offset_addr, 0x3a); + + retval |= pch_phub_write_serial_rom(chip, 0x1f + offset_addr, 0x01); + retval |= pch_phub_write_serial_rom(chip, 0x1e + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x1d + offset_addr, 0x00); + retval |= pch_phub_write_serial_rom(chip, 0x1c + offset_addr, 0x00); + + return retval; +} + /** * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address * @offset_address: Gigabit Ethernet MAC address offset value. @@ -406,7 +464,10 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) int retval; int i; - retval = pch_phub_gbe_serial_rom_conf(chip); + if (chip->ioh_type == 1) /* EG20T */ + retval = pch_phub_gbe_serial_rom_conf(chip); + else /* ML7223 */ + retval = pch_phub_gbe_serial_rom_conf_mp(chip); if (retval) return retval; @@ -441,12 +502,16 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, } /* Get Rom signature */ - pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature); + pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address, + (unsigned char *)&rom_signature); rom_signature &= 0xff; - pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp); + pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address + 1, + (unsigned char *)&tmp); rom_signature |= (tmp & 0xff) << 8; if (rom_signature == 0xAA55) { - pch_phub_read_serial_rom(chip, 0x82, &rom_length); + pch_phub_read_serial_rom(chip, + chip->pch_opt_rom_start_address + 2, + &rom_length); orom_size = rom_length * 512; if (orom_size < off) { addr_offset = 0; @@ -458,8 +523,9 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, } for (addr_offset = 0; addr_offset < count; addr_offset++) { - pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off, - &buf[addr_offset]); + pch_phub_read_serial_rom(chip, + chip->pch_opt_rom_start_address + addr_offset + off, + &buf[addr_offset]); } } else { err = -ENODATA; @@ -502,8 +568,9 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, if (PCH_PHUB_OROM_SIZE < off + addr_offset) goto return_ok; - ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off, - buf[addr_offset]); + ret = pch_phub_write_serial_rom(chip, + chip->pch_opt_rom_start_address + addr_offset + off, + buf[addr_offset]); if (ret) { err = ret; goto return_err; @@ -603,19 +670,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value " "in pch_phub_base_address variable is %p\n", __func__, chip->pch_phub_base_address); - chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size); - if (chip->pch_phub_extrom_base_address == 0) { - dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__); - ret = -ENOMEM; - goto err_pci_map; + if (id->driver_data != 3) { + chip->pch_phub_extrom_base_address =\ + pci_map_rom(pdev, &rom_size); + if (chip->pch_phub_extrom_base_address == 0) { + dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__); + ret = -ENOMEM; + goto err_pci_map; + } + dev_dbg(&pdev->dev, "%s : " + "pci_map_rom SUCCESS and value in " + "pch_phub_extrom_base_address variable is %p\n", + __func__, chip->pch_phub_extrom_base_address); } - dev_dbg(&pdev->dev, "%s : " - "pci_map_rom SUCCESS and value in " - "pch_phub_extrom_base_address variable is %p\n", __func__, - chip->pch_phub_extrom_base_address); - if (id->driver_data == 1) { + if (id->driver_data == 1) { /* EG20T PCH */ retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); if (retval) @@ -642,7 +712,9 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); /* set the interrupt delay value */ iowrite32(0x25, chip->pch_phub_base_address + 0x44); - } else if (id->driver_data == 2) { + chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; + chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; + } else if (id->driver_data == 2) { /* ML7213 IOH */ retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); if (retval) goto err_sysfs_create; @@ -653,7 +725,38 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, * Device8(USB OHCI #0/ USB EHCI #0):a */ iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); + chip->pch_opt_rom_start_address =\ + PCH_PHUB_ROM_START_ADDR_ML7213; + } else if (id->driver_data == 3) { /* ML7223 IOH Bus-m*/ + /* set the prefech value + * Device8(GbE) + */ + iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14); + chip->pch_opt_rom_start_address =\ + PCH_PHUB_ROM_START_ADDR_ML7223; + chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; + } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/ + retval = sysfs_create_file(&pdev->dev.kobj, + &dev_attr_pch_mac.attr); + if (retval) + goto err_sysfs_create; + retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); + if (retval) + goto exit_bin_attr; + /* set the prefech value + * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a + * Device4(SDIO #0,1):f + * Device6(SATA 2):f + */ + iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14); + /* set the interrupt delay value */ + iowrite32(0x25, chip->pch_phub_base_address + 0x140); + chip->pch_opt_rom_start_address =\ + PCH_PHUB_ROM_START_ADDR_ML7223; + chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; } + + chip->ioh_type = id->driver_data; pci_set_drvdata(pdev, chip); return 0; @@ -733,6 +836,8 @@ static int pch_phub_resume(struct pci_dev *pdev) static struct pci_device_id pch_phub_pcidev_id[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, }, { } }; MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); @@ -759,5 +864,5 @@ static void __exit pch_phub_pci_exit(void) module_init(pch_phub_pci_init); module_exit(pch_phub_pci_exit); -MODULE_DESCRIPTION("PCH Packet Hub PCI Driver"); +MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"); MODULE_LICENSE("GPL"); -- cgit v1.2.2 From e0f263d719cc70245406cc26d86a480925e6a3c9 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Thu, 12 May 2011 10:08:09 +0900 Subject: tty: Remove to support serial for S5P6442 According to removing ARCH_S5P6442, we don't need to support serial for S5P6442. Cc: Alan Cox Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2f96ce9924b..c01af80d12a 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -537,7 +537,7 @@ config SERIAL_S3C6400 config SERIAL_S5PV210 tristate "Samsung S5PV210 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_EXYNOS4210) + depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210) select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210) default y help -- cgit v1.2.2 From 7d74f492e4dd0034a61458eb80f70b1d2862ed07 Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Fri, 6 May 2011 16:56:47 -0700 Subject: export kernel call get_task_comm(). This allows drivers who call this function to be compiled modularly. Otherwise, a driver who is interested in this type of functionality has to implement their own get_task_comm() call, causing code duplication in the Linux source tree. Signed-off-by: J Freyensee Acked-by: David Rientjes Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/exec.c b/fs/exec.c index 5e62d26a4fe..7de94950a5b 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1004,6 +1004,7 @@ char *get_task_comm(char *buf, struct task_struct *tsk) task_unlock(tsk); return buf; } +EXPORT_SYMBOL_GPL(get_task_comm); void set_task_comm(struct task_struct *tsk, char *buf) { -- cgit v1.2.2 From cb9e84c4123088f4641009f5217b7d32b307992f Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Fri, 6 May 2011 16:56:48 -0700 Subject: Kernel documentation for the PTI feature. This provides Kernel documentation for the PTI feature and setting line discipline drivers on top of tty's for Linux mobile solutions. Signed-off-by: J Freyensee Signed-off-by: Greg Kroah-Hartman --- Documentation/pti/pti_intel_mid.txt | 99 +++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Documentation/pti/pti_intel_mid.txt diff --git a/Documentation/pti/pti_intel_mid.txt b/Documentation/pti/pti_intel_mid.txt new file mode 100644 index 00000000000..e7a5b6d1f7a --- /dev/null +++ b/Documentation/pti/pti_intel_mid.txt @@ -0,0 +1,99 @@ +The Intel MID PTI project is HW implemented in Intel Atom +system-on-a-chip designs based on the Parallel Trace +Interface for MIPI P1149.7 cJTAG standard. The kernel solution +for this platform involves the following files: + +./include/linux/pti.h +./drivers/.../n_tracesink.h +./drivers/.../n_tracerouter.c +./drivers/.../n_tracesink.c +./drivers/.../pti.c + +pti.c is the driver that enables various debugging features +popular on platforms from certain mobile manufacturers. +n_tracerouter.c and n_tracesink.c allow extra system information to +be collected and routed to the pti driver, such as trace +debugging data from a modem. Although n_tracerouter +and n_tracesink are a part of the complete PTI solution, +these two line disciplines can work separately from +pti.c and route any data stream from one /dev/tty node +to another /dev/tty node via kernel-space. This provides +a stable, reliable connection that will not break unless +the user-space application shuts down (plus avoids +kernel->user->kernel context switch overheads of routing +data). + +An example debugging usage for this driver system: + *Hook /dev/ttyPTI0 to syslogd. Opening this port will also start + a console device to further capture debugging messages to PTI. + *Hook /dev/ttyPTI1 to modem debugging data to write to PTI HW. + This is where n_tracerouter and n_tracesink are used. + *Hook /dev/pti to a user-level debugging application for writing + to PTI HW. + *Use mipi_* Kernel Driver API in other device drivers for + debugging to PTI by first requesting a PTI write address via + mipi_request_masterchannel(1). + +Below is example pseudo-code on how a 'privileged' application +can hook up n_tracerouter and n_tracesink to any tty on +a system. 'Privileged' means the application has enough +privileges to successfully manipulate the ldisc drivers +but is not just blindly executing as 'root'. Keep in mind +the use of ioctl(,TIOCSETD,) is not specific to the n_tracerouter +and n_tracesink line discpline drivers but is a generic +operation for a program to use a line discpline driver +on a tty port other than the default n_tty. + +/////////// To hook up n_tracerouter and n_tracesink ///////// + +// Note that n_tracerouter depends on n_tracesink. +#include +#define ONE_TTY "/dev/ttyOne" +#define TWO_TTY "/dev/ttyTwo" + +// needed global to hand onto ldisc connection +static int g_fd_source = -1; +static int g_fd_sink = -1; + +// these two vars used to grab LDISC values from loaded ldisc drivers +// in OS. Look at /proc/tty/ldiscs to get the right numbers from +// the ldiscs loaded in the system. +int source_ldisc_num, sink_ldisc_num = -1; +int retval; + +g_fd_source = open(ONE_TTY, O_RDWR); // must be R/W +g_fd_sink = open(TWO_TTY, O_RDWR); // must be R/W + +if (g_fd_source <= 0) || (g_fd_sink <= 0) { + // doubt you'll want to use these exact error lines of code + printf("Error on open(). errno: %d\n",errno); + return errno; +} + +retval = ioctl(g_fd_sink, TIOCSETD, &sink_ldisc_num); +if (retval < 0) { + printf("Error on ioctl(). errno: %d\n", errno); + return errno; +} + +retval = ioctl(g_fd_source, TIOCSETD, &source_ldisc_num); +if (retval < 0) { + printf("Error on ioctl(). errno: %d\n", errno); + return errno; +} + +/////////// To disconnect n_tracerouter and n_tracesink //////// + +// First make sure data through the ldiscs has stopped. + +// Second, disconnect ldiscs. This provides a +// little cleaner shutdown on tty stack. +sink_ldisc_num = 0; +source_ldisc_num = 0; +ioctl(g_fd_uart, TIOCSETD, &sink_ldisc_num); +ioctl(g_fd_gadget, TIOCSETD, &source_ldisc_num); + +// Three, program closes connection, and cleanup: +close(g_fd_uart); +close(g_fd_gadget); +g_fd_uart = g_fd_gadget = NULL; -- cgit v1.2.2 From 0b61d2acb1ea48d8eba798ed92759b7f1b0f4209 Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Fri, 6 May 2011 16:56:49 -0700 Subject: Intel PTI implementaiton of MIPI 1149.7. The PTI (Parallel Trace Interface) driver directs trace data routed from various parts in the system out through an Intel Penwell PTI port and out of the mobile device for analysis with a debugging tool (Lauterbach or Fido). Though n_tracesink and n_tracerouter line discipline drivers are used to extract modem tracing data to the PTI driver and other parts of an Intel mobile solution, the PTI driver can be used independent of n_tracesink and n_tracerouter. You should select this driver if the target kernel is meant for an Intel Atom (non-netbook) mobile device containing a MIPI P1149.7 standard implementation. Signed-off-by: J Freyensee Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 13 + drivers/misc/Makefile | 1 + drivers/misc/pti.c | 980 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pti.h | 42 +++ 4 files changed, 1036 insertions(+) create mode 100644 drivers/misc/pti.c create mode 100644 include/linux/pti.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 915c31ef84c..ec33d939548 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -144,6 +144,19 @@ config PHANTOM If you choose to build module, its name will be phantom. If unsure, say N here. +config INTEL_MID_PTI + tristate "Parallel Trace Interface for MIPI P1149.7 cJTAG standard" + default n + help + The PTI (Parallel Trace Interface) driver directs + trace data routed from various parts in the system out + through an Intel Penwell PTI port and out of the mobile + device for analysis with a debugging tool (Lauterbach or Fido). + + You should select this driver if the target kernel is meant for + an Intel Atom (non-netbook) mobile device containing a MIPI + P1149.7 standard implementation. + config SGI_IOC4 tristate "SGI IOC4 Base IO support" depends on PCI diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index f5468602961..662aa3c71d0 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o +0bj-$(CONFIG_INTEL_MID_PTI) += pti.o obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c new file mode 100644 index 00000000000..bb6f9255c17 --- /dev/null +++ b/drivers/misc/pti.c @@ -0,0 +1,980 @@ +/* + * pti.c - PTI driver for cJTAG data extration + * + * Copyright (C) Intel 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The PTI (Parallel Trace Interface) driver directs trace data routed from + * various parts in the system out through the Intel Penwell PTI port and + * out of the mobile device for analysis with a debugging tool + * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7, + * compact JTAG, standard. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVERNAME "pti" +#define PCINAME "pciPTI" +#define TTYNAME "ttyPTI" +#define CHARNAME "pti" +#define PTITTY_MINOR_START 0 +#define PTITTY_MINOR_NUM 2 +#define MAX_APP_IDS 16 /* 128 channel ids / u8 bit size */ +#define MAX_OS_IDS 16 /* 128 channel ids / u8 bit size */ +#define MAX_MODEM_IDS 16 /* 128 channel ids / u8 bit size */ +#define MODEM_BASE_ID 71 /* modem master ID address */ +#define CONTROL_ID 72 /* control master ID address */ +#define CONSOLE_ID 73 /* console master ID address */ +#define OS_BASE_ID 74 /* base OS master ID address */ +#define APP_BASE_ID 80 /* base App master ID address */ +#define CONTROL_FRAME_LEN 32 /* PTI control frame maximum size */ +#define USER_COPY_SIZE 8192 /* 8Kb buffer for user space copy */ +#define APERTURE_14 0x3800000 /* offset to first OS write addr */ +#define APERTURE_LEN 0x400000 /* address length */ + +struct pti_tty { + struct pti_masterchannel *mc; +}; + +struct pti_dev { + struct tty_port port; + unsigned long pti_addr; + unsigned long aperture_base; + void __iomem *pti_ioaddr; + u8 ia_app[MAX_APP_IDS]; + u8 ia_os[MAX_OS_IDS]; + u8 ia_modem[MAX_MODEM_IDS]; +}; + +/* + * This protects access to ia_app, ia_os, and ia_modem, + * which keeps track of channels allocated in + * an aperture write id. + */ +static DEFINE_MUTEX(alloclock); + +static struct pci_device_id pci_ids[] __devinitconst = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)}, + {0} +}; + +static struct tty_driver *pti_tty_driver; +static struct pti_dev *drv_data; + +static unsigned int pti_console_channel; +static unsigned int pti_control_channel; + +/** + * pti_write_to_aperture()- The private write function to PTI HW. + * + * @mc: The 'aperture'. It's part of a write address that holds + * a master and channel ID. + * @buf: Data being written to the HW that will ultimately be seen + * in a debugging tool (Fido, Lauterbach). + * @len: Size of buffer. + * + * Since each aperture is specified by a unique + * master/channel ID, no two processes will be writing + * to the same aperture at the same time so no lock is required. The + * PTI-Output agent will send these out in the order that they arrived, and + * thus, it will intermix these messages. The debug tool can then later + * regroup the appropriate message segments together reconstituting each + * message. + */ +static void pti_write_to_aperture(struct pti_masterchannel *mc, + u8 *buf, + int len) +{ + int dwordcnt; + int final; + int i; + u32 ptiword; + u32 __iomem *aperture; + u8 *p = buf; + + /* + * calculate the aperture offset from the base using the master and + * channel id's. + */ + aperture = drv_data->pti_ioaddr + (mc->master << 15) + + (mc->channel << 8); + + dwordcnt = len >> 2; + final = len - (dwordcnt << 2); /* final = trailing bytes */ + if (final == 0 && dwordcnt != 0) { /* always need a final dword */ + final += 4; + dwordcnt--; + } + + for (i = 0; i < dwordcnt; i++) { + ptiword = be32_to_cpu(*(u32 *)p); + p += 4; + iowrite32(ptiword, aperture); + } + + aperture += PTI_LASTDWORD_DTS; /* adding DTS signals that is EOM */ + + ptiword = 0; + for (i = 0; i < final; i++) + ptiword |= *p++ << (24-(8*i)); + + iowrite32(ptiword, aperture); + return; +} + +/** + * pti_control_frame_built_and_sent()- control frame build and send function. + * + * @mc: The master / channel structure on which the function + * built a control frame. + * + * To be able to post process the PTI contents on host side, a control frame + * is added before sending any PTI content. So the host side knows on + * each PTI frame the name of the thread using a dedicated master / channel. + * The thread name is retrieved from the 'current' global variable. + * This function builds this frame and sends it to a master ID CONTROL_ID. + * The overhead is only 32 bytes since the driver only writes to HW + * in 32 byte chunks. + */ + +static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc) +{ + struct pti_masterchannel mccontrol = {.master = CONTROL_ID, + .channel = 0}; + const char *control_format = "%3d %3d %s"; + u8 control_frame[CONTROL_FRAME_LEN]; + + /* + * Since we access the comm member in current's task_struct, + * we only need to be as large as what 'comm' in that + * structure is. + */ + char comm[TASK_COMM_LEN]; + + if (!in_interrupt()) + get_task_comm(comm, current); + else + strncpy(comm, "Interrupt", TASK_COMM_LEN); + + /* Absolutely ensure our buffer is zero terminated. */ + comm[TASK_COMM_LEN-1] = 0; + + mccontrol.channel = pti_control_channel; + pti_control_channel = (pti_control_channel + 1) & 0x7f; + + snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master, + mc->channel, comm); + pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame)); +} + +/** + * pti_write_full_frame_to_aperture()- high level function to + * write to PTI. + * + * @mc: The 'aperture'. It's part of a write address that holds + * a master and channel ID. + * @buf: Data being written to the HW that will ultimately be seen + * in a debugging tool (Fido, Lauterbach). + * @len: Size of buffer. + * + * All threads sending data (either console, user space application, ...) + * are calling the high level function to write to PTI meaning that it is + * possible to add a control frame before sending the content. + */ +static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc, + const unsigned char *buf, + int len) +{ + pti_control_frame_built_and_sent(mc); + pti_write_to_aperture(mc, (u8 *)buf, len); +} + +/** + * get_id()- Allocate a master and channel ID. + * + * @id_array: an array of bits representing what channel + * id's are allocated for writing. + * @max_ids: The max amount of available write IDs to use. + * @base_id: The starting SW channel ID, based on the Intel + * PTI arch. + * + * Returns: + * pti_masterchannel struct with master, channel ID address + * 0 for error + * + * Each bit in the arrays ia_app and ia_os correspond to a master and + * channel id. The bit is one if the id is taken and 0 if free. For + * every master there are 128 channel id's. + */ +static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id) +{ + struct pti_masterchannel *mc; + int i, j, mask; + + mc = kmalloc(sizeof(struct pti_masterchannel), GFP_KERNEL); + if (mc == NULL) + return NULL; + + /* look for a byte with a free bit */ + for (i = 0; i < max_ids; i++) + if (id_array[i] != 0xff) + break; + if (i == max_ids) { + kfree(mc); + return NULL; + } + /* find the bit in the 128 possible channel opportunities */ + mask = 0x80; + for (j = 0; j < 8; j++) { + if ((id_array[i] & mask) == 0) + break; + mask >>= 1; + } + + /* grab it */ + id_array[i] |= mask; + mc->master = base_id; + mc->channel = ((i & 0xf)<<3) + j; + /* write new master Id / channel Id allocation to channel control */ + pti_control_frame_built_and_sent(mc); + return mc; +} + +/* + * The following three functions: + * pti_request_mastercahannel(), mipi_release_masterchannel() + * and pti_writedata() are an API for other kernel drivers to + * access PTI. + */ + +/** + * pti_request_masterchannel()- Kernel API function used to allocate + * a master, channel ID address + * to write to PTI HW. + * + * @type: 0- request Application master, channel aperture ID write address. + * 1- request OS master, channel aperture ID write + * address. + * 2- request Modem master, channel aperture ID + * write address. + * Other values, error. + * + * Returns: + * pti_masterchannel struct + * 0 for error + */ +struct pti_masterchannel *pti_request_masterchannel(u8 type) +{ + struct pti_masterchannel *mc; + + mutex_lock(&alloclock); + + switch (type) { + + case 0: + mc = get_id(drv_data->ia_app, MAX_APP_IDS, APP_BASE_ID); + break; + + case 1: + mc = get_id(drv_data->ia_os, MAX_OS_IDS, OS_BASE_ID); + break; + + case 2: + mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS, MODEM_BASE_ID); + break; + default: + mc = NULL; + } + + mutex_unlock(&alloclock); + return mc; +} +EXPORT_SYMBOL_GPL(pti_request_masterchannel); + +/** + * pti_release_masterchannel()- Kernel API function used to release + * a master, channel ID address + * used to write to PTI HW. + * + * @mc: master, channel apeture ID address to be released. + */ +void pti_release_masterchannel(struct pti_masterchannel *mc) +{ + u8 master, channel, i; + + mutex_lock(&alloclock); + + if (mc) { + master = mc->master; + channel = mc->channel; + + if (master == APP_BASE_ID) { + i = channel >> 3; + drv_data->ia_app[i] &= ~(0x80>>(channel & 0x7)); + } else if (master == OS_BASE_ID) { + i = channel >> 3; + drv_data->ia_os[i] &= ~(0x80>>(channel & 0x7)); + } else { + i = channel >> 3; + drv_data->ia_modem[i] &= ~(0x80>>(channel & 0x7)); + } + + kfree(mc); + } + + mutex_unlock(&alloclock); +} +EXPORT_SYMBOL_GPL(pti_release_masterchannel); + +/** + * pti_writedata()- Kernel API function used to write trace + * debugging data to PTI HW. + * + * @mc: Master, channel aperture ID address to write to. + * Null value will return with no write occurring. + * @buf: Trace debuging data to write to the PTI HW. + * Null value will return with no write occurring. + * @count: Size of buf. Value of 0 or a negative number will + * return with no write occuring. + */ +void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count) +{ + /* + * since this function is exported, this is treated like an + * API function, thus, all parameters should + * be checked for validity. + */ + if ((mc != NULL) && (buf != NULL) && (count > 0)) + pti_write_to_aperture(mc, buf, count); + return; +} +EXPORT_SYMBOL_GPL(pti_writedata); + +/** + * pti_pci_remove()- Driver exit method to remove PTI from + * PCI bus. + * @pdev: variable containing pci info of PTI. + */ +static void __devexit pti_pci_remove(struct pci_dev *pdev) +{ + struct pti_dev *drv_data; + + drv_data = pci_get_drvdata(pdev); + if (drv_data != NULL) { + pci_iounmap(pdev, drv_data->pti_ioaddr); + pci_set_drvdata(pdev, NULL); + kfree(drv_data); + pci_release_region(pdev, 1); + pci_disable_device(pdev); + } +} + +/* + * for the tty_driver_*() basic function descriptions, see tty_driver.h. + * Specific header comments made for PTI-related specifics. + */ + +/** + * pti_tty_driver_open()- Open an Application master, channel aperture + * ID to the PTI device via tty device. + * + * @tty: tty interface. + * @filp: filp interface pased to tty_port_open() call. + * + * Returns: + * int, 0 for success + * otherwise, fail value + * + * The main purpose of using the tty device interface is for + * each tty port to have a unique PTI write aperture. In an + * example use case, ttyPTI0 gets syslogd and an APP aperture + * ID and ttyPTI1 is where the n_tracesink ldisc hooks to route + * modem messages into PTI. Modem trace data does not have to + * go to ttyPTI1, but ttyPTI0 and ttyPTI1 do need to be distinct + * master IDs. These messages go through the PTI HW and out of + * the handheld platform and to the Fido/Lauterbach device. + */ +static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp) +{ + /* + * we actually want to allocate a new channel per open, per + * system arch. HW gives more than plenty channels for a single + * system task to have its own channel to write trace data. This + * also removes a locking requirement for the actual write + * procedure. + */ + return tty_port_open(&drv_data->port, tty, filp); +} + +/** + * pti_tty_driver_close()- close tty device and release Application + * master, channel aperture ID to the PTI device via tty device. + * + * @tty: tty interface. + * @filp: filp interface pased to tty_port_close() call. + * + * The main purpose of using the tty device interface is to route + * syslog daemon messages to the PTI HW and out of the handheld platform + * and to the Fido/Lauterbach device. + */ +static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp) +{ + tty_port_close(&drv_data->port, tty, filp); +} + +/** + * pti_tty_intstall()- Used to set up specific master-channels + * to tty ports for organizational purposes when + * tracing viewed from debuging tools. + * + * @driver: tty driver information. + * @tty: tty struct containing pti information. + * + * Returns: + * 0 for success + * otherwise, error + */ +static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty) +{ + int idx = tty->index; + struct pti_tty *pti_tty_data; + int ret = tty_init_termios(tty); + + if (ret == 0) { + tty_driver_kref_get(driver); + tty->count++; + driver->ttys[idx] = tty; + + pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL); + if (pti_tty_data == NULL) + return -ENOMEM; + + if (idx == PTITTY_MINOR_START) + pti_tty_data->mc = pti_request_masterchannel(0); + else + pti_tty_data->mc = pti_request_masterchannel(2); + + if (pti_tty_data->mc == NULL) + return -ENXIO; + tty->driver_data = pti_tty_data; + } + + return ret; +} + +/** + * pti_tty_cleanup()- Used to de-allocate master-channel resources + * tied to tty's of this driver. + * + * @tty: tty struct containing pti information. + */ +static void pti_tty_cleanup(struct tty_struct *tty) +{ + struct pti_tty *pti_tty_data = tty->driver_data; + if (pti_tty_data == NULL) + return; + pti_release_masterchannel(pti_tty_data->mc); + kfree(tty->driver_data); + tty->driver_data = NULL; +} + +/** + * pti_tty_driver_write()- Write trace debugging data through the char + * interface to the PTI HW. Part of the misc device implementation. + * + * @filp: Contains private data which is used to obtain + * master, channel write ID. + * @data: trace data to be written. + * @len: # of byte to write. + * + * Returns: + * int, # of bytes written + * otherwise, error + */ +static int pti_tty_driver_write(struct tty_struct *tty, + const unsigned char *buf, int len) +{ + struct pti_tty *pti_tty_data = tty->driver_data; + if ((pti_tty_data != NULL) && (pti_tty_data->mc != NULL)) { + pti_write_to_aperture(pti_tty_data->mc, (u8 *)buf, len); + return len; + } + /* + * we can't write to the pti hardware if the private driver_data + * and the mc address is not there. + */ + else + return -EFAULT; +} + +/** + * pti_tty_write_room()- Always returns 2048. + * + * @tty: contains tty info of the pti driver. + */ +static int pti_tty_write_room(struct tty_struct *tty) +{ + return 2048; +} + +/** + * pti_char_open()- Open an Application master, channel aperture + * ID to the PTI device. Part of the misc device implementation. + * + * @inode: not used. + * @filp: Output- will have a masterchannel struct set containing + * the allocated application PTI aperture write address. + * + * Returns: + * int, 0 for success + * otherwise, a fail value + */ +static int pti_char_open(struct inode *inode, struct file *filp) +{ + struct pti_masterchannel *mc; + + /* + * We really do want to fail immediately if + * pti_request_masterchannel() fails, + * before assigning the value to filp->private_data. + * Slightly easier to debug if this driver needs debugging. + */ + mc = pti_request_masterchannel(0); + if (mc == NULL) + return -ENOMEM; + filp->private_data = mc; + return 0; +} + +/** + * pti_char_release()- Close a char channel to the PTI device. Part + * of the misc device implementation. + * + * @inode: Not used in this implementaiton. + * @filp: Contains private_data that contains the master, channel + * ID to be released by the PTI device. + * + * Returns: + * always 0 + */ +static int pti_char_release(struct inode *inode, struct file *filp) +{ + pti_release_masterchannel(filp->private_data); + kfree(filp->private_data); + return 0; +} + +/** + * pti_char_write()- Write trace debugging data through the char + * interface to the PTI HW. Part of the misc device implementation. + * + * @filp: Contains private data which is used to obtain + * master, channel write ID. + * @data: trace data to be written. + * @len: # of byte to write. + * @ppose: Not used in this function implementation. + * + * Returns: + * int, # of bytes written + * otherwise, error value + * + * Notes: From side discussions with Alan Cox and experimenting + * with PTI debug HW like Nokia's Fido box and Lauterbach + * devices, 8192 byte write buffer used by USER_COPY_SIZE was + * deemed an appropriate size for this type of usage with + * debugging HW. + */ +static ssize_t pti_char_write(struct file *filp, const char __user *data, + size_t len, loff_t *ppose) +{ + struct pti_masterchannel *mc; + void *kbuf; + const char __user *tmp; + size_t size = USER_COPY_SIZE; + size_t n = 0; + + tmp = data; + mc = filp->private_data; + + kbuf = kmalloc(size, GFP_KERNEL); + if (kbuf == NULL) { + pr_err("%s(%d): buf allocation failed\n", + __func__, __LINE__); + return -ENOMEM; + } + + do { + if (len - n > USER_COPY_SIZE) + size = USER_COPY_SIZE; + else + size = len - n; + + if (copy_from_user(kbuf, tmp, size)) { + kfree(kbuf); + return n ? n : -EFAULT; + } + + pti_write_to_aperture(mc, kbuf, size); + n += size; + tmp += size; + + } while (len > n); + + kfree(kbuf); + return len; +} + +static const struct tty_operations pti_tty_driver_ops = { + .open = pti_tty_driver_open, + .close = pti_tty_driver_close, + .write = pti_tty_driver_write, + .write_room = pti_tty_write_room, + .install = pti_tty_install, + .cleanup = pti_tty_cleanup +}; + +static const struct file_operations pti_char_driver_ops = { + .owner = THIS_MODULE, + .write = pti_char_write, + .open = pti_char_open, + .release = pti_char_release, +}; + +static struct miscdevice pti_char_driver = { + .minor = MISC_DYNAMIC_MINOR, + .name = CHARNAME, + .fops = &pti_char_driver_ops +}; + +/** + * pti_console_write()- Write to the console that has been acquired. + * + * @c: Not used in this implementaiton. + * @buf: Data to be written. + * @len: Length of buf. + */ +static void pti_console_write(struct console *c, const char *buf, unsigned len) +{ + static struct pti_masterchannel mc = {.master = CONSOLE_ID, + .channel = 0}; + + mc.channel = pti_console_channel; + pti_console_channel = (pti_console_channel + 1) & 0x7f; + + pti_write_full_frame_to_aperture(&mc, buf, len); +} + +/** + * pti_console_device()- Return the driver tty structure and set the + * associated index implementation. + * + * @c: Console device of the driver. + * @index: index associated with c. + * + * Returns: + * always value of pti_tty_driver structure when this function + * is called. + */ +static struct tty_driver *pti_console_device(struct console *c, int *index) +{ + *index = c->index; + return pti_tty_driver; +} + +/** + * pti_console_setup()- Initialize console variables used by the driver. + * + * @c: Not used. + * @opts: Not used. + * + * Returns: + * always 0. + */ +static int pti_console_setup(struct console *c, char *opts) +{ + pti_console_channel = 0; + pti_control_channel = 0; + return 0; +} + +/* + * pti_console struct, used to capture OS printk()'s and shift + * out to the PTI device for debugging. This cannot be + * enabled upon boot because of the possibility of eating + * any serial console printk's (race condition discovered). + * The console should be enabled upon when the tty port is + * used for the first time. Since the primary purpose for + * the tty port is to hook up syslog to it, the tty port + * will be open for a really long time. + */ +static struct console pti_console = { + .name = TTYNAME, + .write = pti_console_write, + .device = pti_console_device, + .setup = pti_console_setup, + .flags = CON_PRINTBUFFER, + .index = 0, +}; + +/** + * pti_port_activate()- Used to start/initialize any items upon + * first opening of tty_port(). + * + * @port- The tty port number of the PTI device. + * @tty- The tty struct associated with this device. + * + * Returns: + * always returns 0 + * + * Notes: The primary purpose of the PTI tty port 0 is to hook + * the syslog daemon to it; thus this port will be open for a + * very long time. + */ +static int pti_port_activate(struct tty_port *port, struct tty_struct *tty) +{ + if (port->tty->index == PTITTY_MINOR_START) + console_start(&pti_console); + return 0; +} + +/** + * pti_port_shutdown()- Used to stop/shutdown any items upon the + * last tty port close. + * + * @port- The tty port number of the PTI device. + * + * Notes: The primary purpose of the PTI tty port 0 is to hook + * the syslog daemon to it; thus this port will be open for a + * very long time. + */ +static void pti_port_shutdown(struct tty_port *port) +{ + if (port->tty->index == PTITTY_MINOR_START) + console_stop(&pti_console); +} + +static const struct tty_port_operations tty_port_ops = { + .activate = pti_port_activate, + .shutdown = pti_port_shutdown, +}; + +/* + * Note the _probe() call sets everything up and ties the char and tty + * to successfully detecting the PTI device on the pci bus. + */ + +/** + * pti_pci_probe()- Used to detect pti on the pci bus and set + * things up in the driver. + * + * @pdev- pci_dev struct values for pti. + * @ent- pci_device_id struct for pti driver. + * + * Returns: + * 0 for success + * otherwise, error + */ +static int __devinit pti_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int retval = -EINVAL; + int pci_bar = 1; + + dev_dbg(&pdev->dev, "%s %s(%d): PTI PCI ID %04x:%04x\n", __FILE__, + __func__, __LINE__, pdev->vendor, pdev->device); + + retval = misc_register(&pti_char_driver); + if (retval) { + pr_err("%s(%d): CHAR registration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + return retval; + } + + retval = pci_enable_device(pdev); + if (retval != 0) { + dev_err(&pdev->dev, + "%s: pci_enable_device() returned error %d\n", + __func__, retval); + return retval; + } + + drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); + + if (drv_data == NULL) { + retval = -ENOMEM; + dev_err(&pdev->dev, + "%s(%d): kmalloc() returned NULL memory.\n", + __func__, __LINE__); + return retval; + } + drv_data->pti_addr = pci_resource_start(pdev, pci_bar); + + retval = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev)); + if (retval != 0) { + dev_err(&pdev->dev, + "%s(%d): pci_request_region() returned error %d\n", + __func__, __LINE__, retval); + kfree(drv_data); + return retval; + } + drv_data->aperture_base = drv_data->pti_addr+APERTURE_14; + drv_data->pti_ioaddr = + ioremap_nocache((u32)drv_data->aperture_base, + APERTURE_LEN); + if (!drv_data->pti_ioaddr) { + pci_release_region(pdev, pci_bar); + retval = -ENOMEM; + kfree(drv_data); + return retval; + } + + pci_set_drvdata(pdev, drv_data); + + tty_port_init(&drv_data->port); + drv_data->port.ops = &tty_port_ops; + + tty_register_device(pti_tty_driver, 0, &pdev->dev); + tty_register_device(pti_tty_driver, 1, &pdev->dev); + + register_console(&pti_console); + + return retval; +} + +static struct pci_driver pti_pci_driver = { + .name = PCINAME, + .id_table = pci_ids, + .probe = pti_pci_probe, + .remove = pti_pci_remove, +}; + +/** + * + * pti_init()- Overall entry/init call to the pti driver. + * It starts the registration process with the kernel. + * + * Returns: + * int __init, 0 for success + * otherwise value is an error + * + */ +static int __init pti_init(void) +{ + int retval = -EINVAL; + + /* First register module as tty device */ + + pti_tty_driver = alloc_tty_driver(1); + if (pti_tty_driver == NULL) { + pr_err("%s(%d): Memory allocation failed for ptiTTY driver\n", + __func__, __LINE__); + return -ENOMEM; + } + + pti_tty_driver->owner = THIS_MODULE; + pti_tty_driver->magic = TTY_DRIVER_MAGIC; + pti_tty_driver->driver_name = DRIVERNAME; + pti_tty_driver->name = TTYNAME; + pti_tty_driver->major = 0; + pti_tty_driver->minor_start = PTITTY_MINOR_START; + pti_tty_driver->minor_num = PTITTY_MINOR_NUM; + pti_tty_driver->num = PTITTY_MINOR_NUM; + pti_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; + pti_tty_driver->subtype = SYSTEM_TYPE_SYSCONS; + pti_tty_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; + pti_tty_driver->init_termios = tty_std_termios; + + tty_set_operations(pti_tty_driver, &pti_tty_driver_ops); + + retval = tty_register_driver(pti_tty_driver); + if (retval) { + pr_err("%s(%d): TTY registration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + + pti_tty_driver = NULL; + return retval; + } + + retval = pci_register_driver(&pti_pci_driver); + + if (retval) { + pr_err("%s(%d): PCI registration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + + tty_unregister_driver(pti_tty_driver); + pr_err("%s(%d): Unregistering TTY part of pti driver\n", + __func__, __LINE__); + pti_tty_driver = NULL; + return retval; + } + + return retval; +} + +/** + * pti_exit()- Unregisters this module as a tty and pci driver. + */ +static void __exit pti_exit(void) +{ + int retval; + + tty_unregister_device(pti_tty_driver, 0); + tty_unregister_device(pti_tty_driver, 1); + + retval = tty_unregister_driver(pti_tty_driver); + if (retval) { + pr_err("%s(%d): TTY unregistration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + } + + pci_unregister_driver(&pti_pci_driver); + + retval = misc_deregister(&pti_char_driver); + if (retval) { + pr_err("%s(%d): CHAR unregistration failed of pti driver\n", + __func__, __LINE__); + pr_err("%s(%d): Error value returned: %d\n", + __func__, __LINE__, retval); + } + + unregister_console(&pti_console); + return; +} + +module_init(pti_init); +module_exit(pti_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ken Mills, Jay Freyensee"); +MODULE_DESCRIPTION("PTI Driver"); + diff --git a/include/linux/pti.h b/include/linux/pti.h new file mode 100644 index 00000000000..81af667bb2d --- /dev/null +++ b/include/linux/pti.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) Intel 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The PTI (Parallel Trace Interface) driver directs trace data routed from + * various parts in the system out through the Intel Penwell PTI port and + * out of the mobile device for analysis with a debugging tool + * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7, + * compact JTAG, standard. + * + * This header file will allow other parts of the OS to use the + * interface to write out it's contents for debugging a mobile system. + */ + +#ifndef PTI_H_ +#define PTI_H_ + +/* offset for last dword of any PTI message. Part of MIPI P1149.7 */ +#define PTI_LASTDWORD_DTS 0x30 + +/* basic structure used as a write address to the PTI HW */ +struct pti_masterchannel { + u8 master; + u8 channel; +}; + +/* the following functions are defined in misc/pti.c */ +void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count); +struct pti_masterchannel *pti_request_masterchannel(u8 type); +void pti_release_masterchannel(struct pti_masterchannel *mc); + +#endif /*PTI_H_*/ -- cgit v1.2.2 From ee4f6b4b89665b92ead67deaa2e5d2ffa1af2b5f Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Fri, 6 May 2011 16:56:50 -0700 Subject: n_tracerouter and n_tracesink ldisc additions. The n_tracerouter and n_tracesink line discpline drivers use the Linux tty line discpline framework to route trace data coming from a tty port (say UART for example) to the trace sink line discipline driver and to another tty port(say USB). Those these two line discipline drivers can be used together, independently from pti.c, they are part of the original implementation solution of the MIPI P1149.7, compact JTAG, PTI solution for Intel mobile platforms starting with the Medfield platform. Signed-off-by: J Freyensee Signed-off-by: Greg Kroah-Hartman --- drivers/tty/Kconfig | 31 ++++++ drivers/tty/Makefile | 2 + drivers/tty/n_tracerouter.c | 243 ++++++++++++++++++++++++++++++++++++++++++++ drivers/tty/n_tracesink.c | 238 +++++++++++++++++++++++++++++++++++++++++++ drivers/tty/n_tracesink.h | 36 +++++++ include/linux/tty.h | 2 + 6 files changed, 552 insertions(+) create mode 100644 drivers/tty/n_tracerouter.c create mode 100644 drivers/tty/n_tracesink.c create mode 100644 drivers/tty/n_tracesink.h diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index 3fd7199301b..bd7cc052799 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -319,3 +319,34 @@ config N_GSM This line discipline provides support for the GSM MUX protocol and presents the mux as a set of 61 individual tty devices. +config TRACE_ROUTER + tristate "Trace data router for MIPI P1149.7 cJTAG standard" + depends on TRACE_SINK + default n + help + The trace router uses the Linux tty line discipline framework to + route trace data coming from a tty port (say UART for example) to + the trace sink line discipline driver and to another tty port (say + USB). This is part of a solution for the MIPI P1149.7, compact JTAG, + standard, which is for debugging mobile devices. The PTI driver in + drivers/misc/pti.c defines the majority of this MIPI solution. + + You should select this driver if the target kernel is meant for + a mobile device containing a modem. Then you will need to select + "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline + driver. + +config TRACE_SINK + tristate "Trace data sink for MIPI P1149.7 cJTAG standard" + default n + help + The trace sink uses the Linux line discipline framework to receive + trace data coming from the trace router line discipline driver + to a user-defined tty port target, like USB. + This is to provide a way to extract modem trace data on + devices that do not have a PTI HW module, or just need modem + trace data to come out of a different HW output port. + This is part of a solution for the P1149.7, compact JTAG, standard. + + If you select this option, you need to select + "Trace data router for MIPI P1149.7 cJTAG standard". diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 690522fcb33..ea89b0bd15f 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_AUDIT) += tty_audit.o obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_N_GSM) += n_gsm.o +obj-$(CONFIG_TRACE_ROUTER) += n_tracerouter.o +obj-$(CONFIG_TRACE_SINK) += n_tracesink.o obj-$(CONFIG_R3964) += n_r3964.o obj-y += vt/ diff --git a/drivers/tty/n_tracerouter.c b/drivers/tty/n_tracerouter.c new file mode 100644 index 00000000000..1f063d3aa32 --- /dev/null +++ b/drivers/tty/n_tracerouter.c @@ -0,0 +1,243 @@ +/* + * n_tracerouter.c - Trace data router through tty space + * + * Copyright (C) Intel 2011 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This trace router uses the Linux line discipline framework to route + * trace data coming from a HW Modem to a PTI (Parallel Trace Module) port. + * The solution is not specific to a HW modem and this line disciple can + * be used to route any stream of data in kernel space. + * This is part of a solution for the P1149.7, compact JTAG, standard. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "n_tracesink.h" + +/* + * Other ldisc drivers use 65536 which basically means, + * 'I can always accept 64k' and flow control is off. + * This number is deemed appropriate for this driver. + */ +#define RECEIVE_ROOM 65536 +#define DRIVERNAME "n_tracerouter" + +/* + * struct to hold private configuration data for this ldisc. + * opencalled is used to hold if this ldisc has been opened. + * kref_tty holds the tty reference the ldisc sits on top of. + */ +struct tracerouter_data { + u8 opencalled; + struct tty_struct *kref_tty; +}; +static struct tracerouter_data *tr_data; + +/* lock for when tty reference is being used */ +static DEFINE_MUTEX(routelock); + +/** + * n_tracerouter_open() - Called when a tty is opened by a SW entity. + * @tty: terminal device to the ldisc. + * + * Return: + * 0 for success. + * + * Caveats: This should only be opened one time per SW entity. + */ +static int n_tracerouter_open(struct tty_struct *tty) +{ + int retval = -EEXIST; + + mutex_lock(&routelock); + if (tr_data->opencalled == 0) { + + tr_data->kref_tty = tty_kref_get(tty); + if (tr_data->kref_tty == NULL) { + retval = -EFAULT; + } else { + tr_data->opencalled = 1; + tty->disc_data = tr_data; + tty->receive_room = RECEIVE_ROOM; + tty_driver_flush_buffer(tty); + retval = 0; + } + } + mutex_unlock(&routelock); + return retval; +} + +/** + * n_tracerouter_close() - close connection + * @tty: terminal device to the ldisc. + * + * Called when a software entity wants to close a connection. + */ +static void n_tracerouter_close(struct tty_struct *tty) +{ + struct tracerouter_data *tptr = tty->disc_data; + + mutex_lock(&routelock); + WARN_ON(tptr->kref_tty != tr_data->kref_tty); + tty_driver_flush_buffer(tty); + tty_kref_put(tr_data->kref_tty); + tr_data->kref_tty = NULL; + tr_data->opencalled = 0; + tty->disc_data = NULL; + mutex_unlock(&routelock); +} + +/** + * n_tracerouter_read() - read request from user space + * @tty: terminal device passed into the ldisc. + * @file: pointer to open file object. + * @buf: pointer to the data buffer that gets eventually returned. + * @nr: number of bytes of the data buffer that is returned. + * + * function that allows read() functionality in userspace. By default if this + * is not implemented it returns -EIO. This module is functioning like a + * router via n_tracerouter_receivebuf(), and there is no real requirement + * to implement this function. However, an error return value other than + * -EIO should be used just to show that there was an intent not to have + * this function implemented. Return value based on read() man pages. + * + * Return: + * -EINVAL + */ +static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file, + unsigned char __user *buf, size_t nr) { + return -EINVAL; +} + +/** + * n_tracerouter_write() - Function that allows write() in userspace. + * @tty: terminal device passed into the ldisc. + * @file: pointer to open file object. + * @buf: pointer to the data buffer that gets eventually returned. + * @nr: number of bytes of the data buffer that is returned. + * + * By default if this is not implemented, it returns -EIO. + * This should not be implemented, ever, because + * 1. this driver is functioning like a router via + * n_tracerouter_receivebuf() + * 2. No writes to HW will ever go through this line discpline driver. + * However, an error return value other than -EIO should be used + * just to show that there was an intent not to have this function + * implemented. Return value based on write() man pages. + * + * Return: + * -EINVAL + */ +static ssize_t n_tracerouter_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) { + return -EINVAL; +} + +/** + * n_tracerouter_receivebuf() - Routing function for driver. + * @tty: terminal device passed into the ldisc. It's assumed + * tty will never be NULL. + * @cp: buffer, block of characters to be eventually read by + * someone, somewhere (user read() call or some kernel function). + * @fp: flag buffer. + * @count: number of characters (aka, bytes) in cp. + * + * This function takes the input buffer, cp, and passes it to + * an external API function for processing. + */ +static void n_tracerouter_receivebuf(struct tty_struct *tty, + const unsigned char *cp, + char *fp, int count) +{ + mutex_lock(&routelock); + n_tracesink_datadrain((u8 *) cp, count); + mutex_unlock(&routelock); +} + +/* + * Flush buffer is not impelemented as the ldisc has no internal buffering + * so the tty_driver_flush_buffer() is sufficient for this driver's needs. + */ + +static struct tty_ldisc_ops tty_ptirouter_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = DRIVERNAME, + .open = n_tracerouter_open, + .close = n_tracerouter_close, + .read = n_tracerouter_read, + .write = n_tracerouter_write, + .receive_buf = n_tracerouter_receivebuf +}; + +/** + * n_tracerouter_init - module initialisation + * + * Registers this module as a line discipline driver. + * + * Return: + * 0 for success, any other value error. + */ +static int __init n_tracerouter_init(void) +{ + int retval; + + tr_data = kzalloc(sizeof(struct tracerouter_data), GFP_KERNEL); + if (tr_data == NULL) + return -ENOMEM; + + + /* Note N_TRACEROUTER is defined in linux/tty.h */ + retval = tty_register_ldisc(N_TRACEROUTER, &tty_ptirouter_ldisc); + if (retval < 0) { + pr_err("%s: Registration failed: %d\n", __func__, retval); + kfree(tr_data); + } + return retval; +} + +/** + * n_tracerouter_exit - module unload + * + * Removes this module as a line discipline driver. + */ +static void __exit n_tracerouter_exit(void) +{ + int retval = tty_unregister_ldisc(N_TRACEROUTER); + + if (retval < 0) + pr_err("%s: Unregistration failed: %d\n", __func__, retval); + else + kfree(tr_data); +} + +module_init(n_tracerouter_init); +module_exit(n_tracerouter_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jay Freyensee"); +MODULE_ALIAS_LDISC(N_TRACEROUTER); +MODULE_DESCRIPTION("Trace router ldisc driver"); diff --git a/drivers/tty/n_tracesink.c b/drivers/tty/n_tracesink.c new file mode 100644 index 00000000000..ddce58b973d --- /dev/null +++ b/drivers/tty/n_tracesink.c @@ -0,0 +1,238 @@ +/* + * n_tracesink.c - Trace data router and sink path through tty space. + * + * Copyright (C) Intel 2011 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The trace sink uses the Linux line discipline framework to receive + * trace data coming from the PTI source line discipline driver + * to a user-desired tty port, like USB. + * This is to provide a way to extract modem trace data on + * devices that do not have a PTI HW module, or just need modem + * trace data to come out of a different HW output port. + * This is part of a solution for the P1149.7, compact JTAG, standard. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "n_tracesink.h" + +/* + * Other ldisc drivers use 65536 which basically means, + * 'I can always accept 64k' and flow control is off. + * This number is deemed appropriate for this driver. + */ +#define RECEIVE_ROOM 65536 +#define DRIVERNAME "n_tracesink" + +/* + * there is a quirk with this ldisc is he can write data + * to a tty from anyone calling his kernel API, which + * meets customer requirements in the drivers/misc/pti.c + * project. So he needs to know when he can and cannot write when + * the API is called. In theory, the API can be called + * after an init() but before a successful open() which + * would crash the system if tty is not checked. + */ +static struct tty_struct *this_tty; +static DEFINE_MUTEX(writelock); + +/** + * n_tracesink_open() - Called when a tty is opened by a SW entity. + * @tty: terminal device to the ldisc. + * + * Return: + * 0 for success, + * -EFAULT = couldn't get a tty kref n_tracesink will sit + * on top of + * -EEXIST = open() called successfully once and it cannot + * be called again. + * + * Caveats: open() should only be successful the first time a + * SW entity calls it. + */ +static int n_tracesink_open(struct tty_struct *tty) +{ + int retval = -EEXIST; + + mutex_lock(&writelock); + if (this_tty == NULL) { + this_tty = tty_kref_get(tty); + if (this_tty == NULL) { + retval = -EFAULT; + } else { + tty->disc_data = this_tty; + tty_driver_flush_buffer(tty); + retval = 0; + } + } + mutex_unlock(&writelock); + + return retval; +} + +/** + * n_tracesink_close() - close connection + * @tty: terminal device to the ldisc. + * + * Called when a software entity wants to close a connection. + */ +static void n_tracesink_close(struct tty_struct *tty) +{ + mutex_lock(&writelock); + tty_driver_flush_buffer(tty); + tty_kref_put(this_tty); + this_tty = NULL; + tty->disc_data = NULL; + mutex_unlock(&writelock); +} + +/** + * n_tracesink_read() - read request from user space + * @tty: terminal device passed into the ldisc. + * @file: pointer to open file object. + * @buf: pointer to the data buffer that gets eventually returned. + * @nr: number of bytes of the data buffer that is returned. + * + * function that allows read() functionality in userspace. By default if this + * is not implemented it returns -EIO. This module is functioning like a + * router via n_tracesink_receivebuf(), and there is no real requirement + * to implement this function. However, an error return value other than + * -EIO should be used just to show that there was an intent not to have + * this function implemented. Return value based on read() man pages. + * + * Return: + * -EINVAL + */ +static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file, + unsigned char __user *buf, size_t nr) { + return -EINVAL; +} + +/** + * n_tracesink_write() - Function that allows write() in userspace. + * @tty: terminal device passed into the ldisc. + * @file: pointer to open file object. + * @buf: pointer to the data buffer that gets eventually returned. + * @nr: number of bytes of the data buffer that is returned. + * + * By default if this is not implemented, it returns -EIO. + * This should not be implemented, ever, because + * 1. this driver is functioning like a router via + * n_tracesink_receivebuf() + * 2. No writes to HW will ever go through this line discpline driver. + * However, an error return value other than -EIO should be used + * just to show that there was an intent not to have this function + * implemented. Return value based on write() man pages. + * + * Return: + * -EINVAL + */ +static ssize_t n_tracesink_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) { + return -EINVAL; +} + +/** + * n_tracesink_datadrain() - Kernel API function used to route + * trace debugging data to user-defined + * port like USB. + * + * @buf: Trace debuging data buffer to write to tty target + * port. Null value will return with no write occurring. + * @count: Size of buf. Value of 0 or a negative number will + * return with no write occuring. + * + * Caveat: If this line discipline does not set the tty it sits + * on top of via an open() call, this API function will not + * call the tty's write() call because it will have no pointer + * to call the write(). + */ +void n_tracesink_datadrain(u8 *buf, int count) +{ + mutex_lock(&writelock); + + if ((buf != NULL) && (count > 0) && (this_tty != NULL)) + this_tty->ops->write(this_tty, buf, count); + + mutex_unlock(&writelock); +} +EXPORT_SYMBOL_GPL(n_tracesink_datadrain); + +/* + * Flush buffer is not impelemented as the ldisc has no internal buffering + * so the tty_driver_flush_buffer() is sufficient for this driver's needs. + */ + +/* + * tty_ldisc function operations for this driver. + */ +static struct tty_ldisc_ops tty_n_tracesink = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = DRIVERNAME, + .open = n_tracesink_open, + .close = n_tracesink_close, + .read = n_tracesink_read, + .write = n_tracesink_write +}; + +/** + * n_tracesink_init- module initialisation + * + * Registers this module as a line discipline driver. + * + * Return: + * 0 for success, any other value error. + */ +static int __init n_tracesink_init(void) +{ + /* Note N_TRACESINK is defined in linux/tty.h */ + int retval = tty_register_ldisc(N_TRACESINK, &tty_n_tracesink); + + if (retval < 0) + pr_err("%s: Registration failed: %d\n", __func__, retval); + + return retval; +} + +/** + * n_tracesink_exit - module unload + * + * Removes this module as a line discipline driver. + */ +static void __exit n_tracesink_exit(void) +{ + int retval = tty_unregister_ldisc(N_TRACESINK); + + if (retval < 0) + pr_err("%s: Unregistration failed: %d\n", __func__, retval); +} + +module_init(n_tracesink_init); +module_exit(n_tracesink_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jay Freyensee"); +MODULE_ALIAS_LDISC(N_TRACESINK); +MODULE_DESCRIPTION("Trace sink ldisc driver"); diff --git a/drivers/tty/n_tracesink.h b/drivers/tty/n_tracesink.h new file mode 100644 index 00000000000..a68bb44f1ef --- /dev/null +++ b/drivers/tty/n_tracesink.h @@ -0,0 +1,36 @@ +/* + * n_tracesink.h - Kernel driver API to route trace data in kernel space. + * + * Copyright (C) Intel 2011 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The PTI (Parallel Trace Interface) driver directs trace data routed from + * various parts in the system out through the Intel Penwell PTI port and + * out of the mobile device for analysis with a debugging tool + * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7, + * compact JTAG, standard. + * + * This header file is used by n_tracerouter to be able to send the + * data of it's tty port to the tty port this module sits. This + * mechanism can also be used independent of the PTI module. + * + */ + +#ifndef N_TRACESINK_H_ +#define N_TRACESINK_H_ + +void n_tracesink_datadrain(u8 *buf, int count); + +#endif diff --git a/include/linux/tty.h b/include/linux/tty.h index 4db4ca79f89..d6f05292e45 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -50,6 +50,8 @@ #define N_CAIF 20 /* CAIF protocol for talking to modems */ #define N_GSM0710 21 /* GSM 0710 Mux */ #define N_TI_WL 22 /* for TI's WL BT, FM, GPS combo chips */ +#define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */ +#define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */ /* * This character is the same as _POSIX_VDISABLE: it cannot be used as -- cgit v1.2.2 From 4539c24fe4f92c09ee668ef959d3e8180df619b9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 17 May 2011 16:12:36 -0600 Subject: tty/serial: Add explicit PORT_TEGRA type Tegra's UART is currently auto-detected as PORT_XSCALE due to register bit UART_IER.UUE being writable. However, the Tegra documentation states that this register bit is reserved. Hence, we should not program it. Instead, the documentation specifies that the UART is 16550 compatible. However, Tegra does need register bit UART_IER.RTOIE set, which is not enabled by any 16550 port type. This was not noticed before, since PORT_XSCALE enables CAP_UUE, which conflates both UUE and RTOIE bit programming. This change defines PORT_TEGRA that doesn't set UART_CAP_UUE, but does set UART_CAP_RTOIE, which is a new capability indicating that the RTOIE bit needs to be enabled. Based-on-code-by: Laxman Dewangan Cc: Laxman Dewangan Signed-off-by: Stephen Warren Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250.c | 14 ++++++++++++-- drivers/tty/serial/8250.h | 1 + include/linux/serial_core.h | 3 ++- include/linux/serial_reg.h | 1 + 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 54482d724fe..a5e290de8c9 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -271,7 +271,7 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 32, .tx_loadsz = 32, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_UUE, + .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE, }, [PORT_RM9000] = { .name = "RM9000", @@ -301,6 +301,14 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + [PORT_TEGRA] = { + .name = "Tegra", + .fifo_size = 32, + .tx_loadsz = 8, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | + UART_FCR_T_TRIG_01, + .flags = UART_CAP_FIFO | UART_CAP_RTOIE, + }, }; #if defined(CONFIG_MIPS_ALCHEMY) @@ -2403,7 +2411,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; if (up->capabilities & UART_CAP_UUE) - up->ier |= UART_IER_UUE | UART_IER_RTOIE; + up->ier |= UART_IER_UUE; + if (up->capabilities & UART_CAP_RTOIE) + up->ier |= UART_IER_RTOIE; serial_out(up, UART_IER, up->ier); diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h index d13b586c0f7..6edf4a6a22d 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250.h @@ -42,6 +42,7 @@ struct serial8250_config { #define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */ #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_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 95d479ba514..a5c31146a33 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -45,7 +45,8 @@ #define PORT_OCTEON 17 /* Cavium OCTEON internal UART */ #define PORT_AR7 18 /* Texas Instruments AR7 internal UART */ #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ -#define PORT_MAX_8250 19 /* max port ID */ +#define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ +#define PORT_MAX_8250 20 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index 3ecb71a9e50..5f66e8499fb 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h @@ -57,6 +57,7 @@ * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654 * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750 * TI16C752: 8 16 56 60 8 16 32 56 + * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA */ #define UART_FCR_R_TRIG_00 0x00 #define UART_FCR_R_TRIG_01 0x40 -- cgit v1.2.2 From 5f873bae704cf8b7cbd64b5720912266286c9146 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 17 May 2011 16:12:37 -0600 Subject: tty/serial: Fix break handling for PORT_TEGRA When a break is received, Tegra's UART apparently fills the FIFO with 0 bytes. These must be drained so that they aren't interpreted as actual data received. This allows e.g. MAGIC_SYSRQ to work on Tegra's UARTs. v2: Added FIXME comment to clear_rx_fifo Originally-by: Laxman Dewangan Cc: Laxman Dewangan Signed-off-by: Stephen Warren Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250.c | 28 ++++++++++++++++++++++++++++ include/linux/serial_reg.h | 1 + 2 files changed, 29 insertions(+) diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index a5e290de8c9..b40f7b90c81 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -1433,6 +1433,27 @@ static void serial8250_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } +/* + * 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); +} + static void receive_chars(struct uart_8250_port *up, unsigned int *status) { @@ -1467,6 +1488,13 @@ receive_chars(struct uart_8250_port *up, unsigned int *status) if (lsr & UART_LSR_BI) { lsr &= ~(UART_LSR_FE | UART_LSR_PE); up->port.icount.brk++; + /* + * If tegra port then clear the rx fifo to + * accept another break/character. + */ + if (up->port.type == PORT_TEGRA) + clear_rx_fifo(up); + /* * We do the SysRQ and SAK checking * here because otherwise the break diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index 5f66e8499fb..c75bda37c18 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h @@ -119,6 +119,7 @@ #define UART_MCR_DTR 0x01 /* DTR complement */ #define UART_LSR 5 /* In: Line Status Register */ +#define UART_LSR_FIFOE 0x80 /* Fifo error */ #define UART_LSR_TEMT 0x40 /* Transmitter empty */ #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ #define UART_LSR_BI 0x10 /* Break interrupt indicator */ -- cgit v1.2.2 From d9a0fbfd7bc5d2c42f0fa9bcbdab62c4942d0388 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Wed, 18 May 2011 22:38:30 +0400 Subject: serial: 8250_pci: add support for Cronyx Omega PCI multiserial board. This patch adds support for the Omega-PCI, an 8-port asynchronous multiport adapter for computers with PCI bus [1]. [1] http://www.cronyx.ru/hardware/ompci.html Signed-off-by: Antony Pavlov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250_pci.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 762db97aecd..4b4968a294b 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -971,6 +971,14 @@ ce4100_serial_setup(struct serial_private *priv, return ret; } +static int +pci_omegapci_setup(struct serial_private *priv, + struct pciserial_board *board, + struct uart_port *port, int idx) +{ + return setup_port(priv, port, 2, idx * 8, 0); +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_port *port, int idx) @@ -1011,6 +1019,7 @@ static int skip_tx_en_setup(struct serial_private *priv, #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 +#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1437,6 +1446,16 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .init = pci_oxsemi_tornado_init, .setup = pci_default_setup, }, + /* + * Cronyx Omega PCI (PLX-chip based) + */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_CRONYX_OMEGA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_omegapci_setup, + }, /* * Default "match everything" terminator entry */ @@ -1624,6 +1643,7 @@ enum pci_board_num_t { pbn_ADDIDATA_PCIe_4_3906250, pbn_ADDIDATA_PCIe_8_3906250, pbn_ce4100_1_115200, + pbn_omegapci, }; /* @@ -2319,6 +2339,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 921600, .reg_shift = 2, }, + [pbn_omegapci] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 0x200, + }, }; static const struct pci_device_id softmodem_blacklist[] = { @@ -3816,6 +3842,12 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_ce4100_1_115200 }, + /* + * Cronyx Omega PCI + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_omegapci }, /* * These entries match devices with class COMMUNICATION_SERIAL, -- cgit v1.2.2