diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 08:47:22 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 08:47:22 -0800 |
commit | 94468080220162f74dc6ce5c3e95e5fec8022902 (patch) | |
tree | b1c46b83e4e731b7b4f70bd341267da519958bdb /drivers | |
parent | fb7b096d949fa852442ed9d8f982bce526ccfe7e (diff) | |
parent | 137ee2f5d173a0e859e35bfb900261418eb88ace (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (36 commits)
jsm: fixing error if the driver fails to load
jsm: removing the uart structure and filename on error
tty: Add a new VT mode which is like VT_PROCESS but doesn't require a VT_RELDISP ioctl call
tty: Keep the default buffering to sub-page units
tty: Fix up char drivers request_room usage
tty: Fix the ldisc hangup race
serial: timberdale: Remove dependancies
nozomi: Tidy up the PCI table
nozomi: Fix mutex handling
nozomi: Add tty_port usage
sdio_uart: Use kfifo instead of the messy circ stuff
serial: bcm63xx_uart: allow more than one uart to be registered.
serial: bcm63xx_uart: don't use kfree() on non kmalloced area.
serial: bfin_5xx: pull in linux/io.h for ioremap prototypes
serial: bfin_5xx: kgdboc should accept gdb break only when it is active
serial: bfin_5xx: need to disable DMA TX interrupt too
serial: bfin_5xx: remove useless gpio handling with hard flow control
Char: synclink, remove unnecessary checks
tty: declare MODULE_FIRMWARE in various drivers
ip2: Add module parameter.
...
Diffstat (limited to 'drivers')
33 files changed, 963 insertions, 651 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 4254457d391..b861c08263a 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -158,13 +158,11 @@ static unsigned int cy_isa_addresses[] = { #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) -#ifdef MODULE static long maddr[NR_CARDS]; static int irq[NR_CARDS]; module_param_array(maddr, long, NULL, 0); module_param_array(irq, int, NULL, 0); -#endif #endif /* CONFIG_ISA */ @@ -598,12 +596,6 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, save_car = readb(base_addr + (CyCAR << index)); cy_writeb(base_addr + (CyCAR << index), save_xir); - /* validate the port# (as configured and open) */ - if (channel + chip * 4 >= cinfo->nports) { - cy_writeb(base_addr + (CySRER << index), - readb(base_addr + (CySRER << index)) & ~CyTxRdy); - goto end; - } info = &cinfo->ports[channel + chip * 4]; tty = tty_port_tty_get(&info->port); if (tty == NULL) { @@ -3316,13 +3308,10 @@ static int __init cy_detect_isa(void) unsigned short cy_isa_irq, nboard; void __iomem *cy_isa_address; unsigned short i, j, cy_isa_nchan; -#ifdef MODULE int isparam = 0; -#endif nboard = 0; -#ifdef MODULE /* Check for module parameters */ for (i = 0; i < NR_CARDS; i++) { if (maddr[i] || i) { @@ -3332,7 +3321,6 @@ static int __init cy_detect_isa(void) if (!maddr[i]) break; } -#endif /* scan the address table probing for Cyclom-Y/ISA boards */ for (i = 0; i < NR_ISA_ADDRS; i++) { @@ -3353,11 +3341,10 @@ static int __init cy_detect_isa(void) iounmap(cy_isa_address); continue; } -#ifdef MODULE + if (isparam && i < NR_CARDS && irq[i]) cy_isa_irq = irq[i]; else -#endif /* find out the board's irq by probing */ cy_isa_irq = detect_isa_irq(cy_isa_address); if (cy_isa_irq == 0) { @@ -4208,3 +4195,4 @@ module_exit(cy_cleanup_module); MODULE_LICENSE("GPL"); MODULE_VERSION(CY_VERSION); MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); +MODULE_FIRMWARE("cyzfirm.bin"); diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 4c3b59be286..465185fc0f5 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -146,7 +146,7 @@ static void hvc_console_print(struct console *co, const char *b, return; /* This console adapter was removed so it is not usable. */ - if (vtermnos[index] < 0) + if (vtermnos[index] == -1) return; while (count > 0 || i > 0) { diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 517271c762e..911e1da6def 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -208,6 +208,7 @@ static int DumpFifoBuffer( char __user *, int); static void ip2_init_board(int, const struct firmware *); static unsigned short find_eisa_board(int); +static int ip2_setup(char *str); /***************/ /* Static Data */ @@ -263,7 +264,7 @@ static int tracewrap; /* Macros */ /**********/ -#if defined(MODULE) && defined(IP2DEBUG_OPEN) +#ifdef IP2DEBUG_OPEN #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ tty->name,(pCh->flags), \ tty->count,/*GET_USE_COUNT(module)*/0,s) @@ -285,7 +286,10 @@ MODULE_AUTHOR("Doug McNash"); MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); MODULE_LICENSE("GPL"); +#define MAX_CMD_STR 50 + static int poll_only; +static char cmd[MAX_CMD_STR]; static int Eisa_irq; static int Eisa_slot; @@ -309,6 +313,8 @@ module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); module_param(poll_only, bool, 0); MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); +module_param_string(ip2, cmd, MAX_CMD_STR, 0); +MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); /* for sysfs class support */ static struct class *ip2_class; @@ -487,7 +493,6 @@ static const struct firmware *ip2_request_firmware(void) return fw; } -#ifndef MODULE /****************************************************************************** * ip2_setup: * str: kernel command line string @@ -531,7 +536,6 @@ static int __init ip2_setup(char *str) return 1; } __setup("ip2=", ip2_setup); -#endif /* !MODULE */ static int __init ip2_loadmain(void) { @@ -539,14 +543,20 @@ static int __init ip2_loadmain(void) int err = 0; i2eBordStrPtr pB = NULL; int rc = -1; - struct pci_dev *pdev = NULL; const struct firmware *fw = NULL; + char *str; + + str = cmd; if (poll_only) { /* Hard lock the interrupts to zero */ irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; } + /* Check module parameter with 'ip2=' has been passed or not */ + if (!poll_only && (!strncmp(str, "ip2=", 4))) + ip2_setup(str); + ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); /* process command line arguments to modprobe or @@ -612,6 +622,7 @@ static int __init ip2_loadmain(void) case PCI: #ifdef CONFIG_PCI { + struct pci_dev *pdev = NULL; u32 addr; int status; @@ -626,7 +637,7 @@ static int __init ip2_loadmain(void) if (pci_enable_device(pdev)) { dev_err(&pdev->dev, "can't enable device\n"); - break; + goto out; } ip2config.type[i] = PCI; ip2config.pci_dev[i] = pci_dev_get(pdev); @@ -638,6 +649,8 @@ static int __init ip2_loadmain(void) dev_err(&pdev->dev, "I/O address error\n"); ip2config.irq[i] = pdev->irq; +out: + pci_dev_put(pdev); } #else printk(KERN_ERR "IP2: PCI card specified but PCI " @@ -656,7 +669,6 @@ static int __init ip2_loadmain(void) break; } /* switch */ } /* for */ - pci_dev_put(pdev); for (i = 0; i < IP2_MAX_BOARDS; ++i) { if (ip2config.addr[i]) { @@ -3197,3 +3209,5 @@ static struct pci_device_id ip2main_pci_tbl[] __devinitdata = { }; MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); + +MODULE_FIRMWARE("intelliport2.bin"); diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 300d5bd6cd0..be2e8f9a27c 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -113,6 +113,8 @@ * 64-bit verification */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/firmware.h> #include <linux/kernel.h> @@ -140,7 +142,6 @@ #define InterruptTheCard(base) outw(0, (base) + 0xc) #define ClearInterrupt(base) inw((base) + 0x0a) -#define pr_dbg(str...) pr_debug("ISICOM: " str) #ifdef DEBUG #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) #else @@ -249,8 +250,7 @@ static int lock_card(struct isi_board *card) spin_unlock_irqrestore(&card->card_lock, card->flags); msleep(10); } - printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n", - card->base); + pr_warning("Failed to lock Card (0x%lx)\n", card->base); return 0; /* Failed to acquire the card! */ } @@ -379,13 +379,13 @@ static inline int __isicom_paranoia_check(struct isi_port const *port, char *name, const char *routine) { if (!port) { - printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for " - "dev %s in %s.\n", name, routine); + pr_warning("Warning: bad isicom magic for dev %s in %s.\n", + name, routine); return 1; } if (port->magic != ISICOM_MAGIC) { - printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for " - "dev %s in %s.\n", name, routine); + pr_warning("Warning: NULL isicom port for dev %s in %s.\n", + name, routine); return 1; } @@ -450,8 +450,8 @@ static void isicom_tx(unsigned long _data) if (!(inw(base + 0x02) & (1 << port->channel))) continue; - pr_dbg("txing %d bytes, port%d.\n", txcount, - port->channel + 1); + pr_debug("txing %d bytes, port%d.\n", + txcount, port->channel + 1); outw((port->channel << isi_card[card].shift_count) | txcount, base); residue = NO; @@ -547,8 +547,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) byte_count = header & 0xff; if (channel + 1 > card->port_count) { - printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): " - "%d(channel) > port_count.\n", base, channel+1); + pr_warning("%s(0x%lx): %d(channel) > port_count.\n", + __func__, base, channel+1); outw(0x0000, base+0x04); /* enable interrupts */ spin_unlock(&card->card_lock); return IRQ_HANDLED; @@ -582,14 +582,15 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) if (port->status & ISI_DCD) { if (!(header & ISI_DCD)) { /* Carrier has been lost */ - pr_dbg("interrupt: DCD->low.\n" - ); + pr_debug("%s: DCD->low.\n", + __func__); port->status &= ~ISI_DCD; tty_hangup(tty); } } else if (header & ISI_DCD) { /* Carrier has been detected */ - pr_dbg("interrupt: DCD->high.\n"); + pr_debug("%s: DCD->high.\n", + __func__); port->status |= ISI_DCD; wake_up_interruptible(&port->port.open_wait); } @@ -641,17 +642,19 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) break; case 2: /* Statistics */ - pr_dbg("isicom_interrupt: stats!!!.\n"); + pr_debug("%s: stats!!!\n", __func__); break; default: - pr_dbg("Intr: Unknown code in status packet.\n"); + pr_debug("%s: Unknown code in status packet.\n", + __func__); break; } } else { /* Data Packet */ count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); - pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count); + pr_debug("%s: Can rx %d of %d bytes.\n", + __func__, count, byte_count); word_count = count >> 1; insw(base, rp, word_count); byte_count -= (word_count << 1); @@ -661,8 +664,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) byte_count -= 2; } if (byte_count > 0) { - pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping " - "bytes...\n", base, channel + 1); + pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n", + __func__, base, channel + 1); /* drain out unread xtra data */ while (byte_count > 0) { inw(base); @@ -888,8 +891,8 @@ static void isicom_shutdown_port(struct isi_port *port) struct isi_board *card = port->card; if (--card->count < 0) { - pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", - card->base, card->count); + pr_debug("%s: bad board(0x%lx) count %d.\n", + __func__, card->base, card->count); card->count = 0; } /* last port was closed, shutdown that board too */ @@ -1681,13 +1684,13 @@ static int __init isicom_init(void) retval = tty_register_driver(isicom_normal); if (retval) { - pr_dbg("Couldn't register the dialin driver\n"); + pr_debug("Couldn't register the dialin driver\n"); goto err_puttty; } retval = pci_register_driver(&isicom_driver); if (retval < 0) { - printk(KERN_ERR "ISICOM: Unable to register pci driver.\n"); + pr_err("Unable to register pci driver.\n"); goto err_unrtty; } @@ -1717,3 +1720,8 @@ module_exit(isicom_exit); MODULE_AUTHOR("MultiTech"); MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("isi608.bin"); +MODULE_FIRMWARE("isi608em.bin"); +MODULE_FIRMWARE("isi616em.bin"); +MODULE_FIRMWARE("isi4608.bin"); +MODULE_FIRMWARE("isi4616.bin"); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 63ee3bbc1ce..166495d6a1d 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -164,24 +164,25 @@ static unsigned int moxaFuncTout = HZ / 2; static unsigned int moxaLowWaterChk; static DEFINE_MUTEX(moxa_openlock); static DEFINE_SPINLOCK(moxa_lock); -/* Variables for insmod */ -#ifdef MODULE + static unsigned long baseaddr[MAX_BOARDS]; static unsigned int type[MAX_BOARDS]; static unsigned int numports[MAX_BOARDS]; -#endif MODULE_AUTHOR("William Chen"); MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); MODULE_LICENSE("GPL"); -#ifdef MODULE +MODULE_FIRMWARE("c218tunx.cod"); +MODULE_FIRMWARE("cp204unx.cod"); +MODULE_FIRMWARE("c320tunx.cod"); + module_param_array(type, uint, NULL, 0); MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); module_param_array(baseaddr, ulong, NULL, 0); MODULE_PARM_DESC(baseaddr, "base address"); module_param_array(numports, uint, NULL, 0); MODULE_PARM_DESC(numports, "numports (ignored for C218)"); -#endif + module_param(ttymajor, int, 0); /* @@ -1024,6 +1025,8 @@ static int __init moxa_init(void) { unsigned int isabrds = 0; int retval = 0; + struct moxa_board_conf *brd = moxa_boards; + unsigned int i; printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); @@ -1051,10 +1054,7 @@ static int __init moxa_init(void) } /* Find the boards defined from module args. */ -#ifdef MODULE - { - struct moxa_board_conf *brd = moxa_boards; - unsigned int i; + for (i = 0; i < MAX_BOARDS; i++) { if (!baseaddr[i]) break; @@ -1087,8 +1087,6 @@ static int __init moxa_init(void) isabrds++; } } - } -#endif #ifdef CONFIG_PCI retval = pci_register_driver(&moxa_pci_driver); diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3d923065d9a..e0c5d2a6904 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -895,8 +895,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty) if (inb(info->ioaddr + UART_LSR) == 0xff) { spin_unlock_irqrestore(&info->slock, flags); if (capable(CAP_SYS_ADMIN)) { - if (tty) - set_bit(TTY_IO_ERROR, &tty->flags); + set_bit(TTY_IO_ERROR, &tty->flags); return 0; } else return -ENODEV; diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 2ad7d37afbd..a3f32a15fde 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -136,10 +136,6 @@ static int debug; #define RECEIVE_BUF_MAX 4 -/* Define all types of vendors and devices to support */ -#define VENDOR1 0x1931 /* Vendor Option */ -#define DEVICE1 0x000c /* HSDPA card */ - #define R_IIR 0x0000 /* Interrupt Identity Register */ #define R_FCR 0x0000 /* Flow Control Register */ #define R_IER 0x0004 /* Interrupt Enable Register */ @@ -371,6 +367,8 @@ struct port { struct mutex tty_sem; wait_queue_head_t tty_wait; struct async_icount tty_icount; + + struct nozomi *dc; }; /* Private data one for each card in the system */ @@ -405,7 +403,7 @@ struct buffer { /* Global variables */ static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { - {PCI_DEVICE(VENDOR1, DEVICE1)}, + {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ {}, }; @@ -414,6 +412,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; static struct tty_driver *ntty_driver; +static const struct tty_port_operations noz_tty_port_ops; + /* * find card by tty_index */ @@ -853,8 +853,6 @@ static int receive_data(enum port_type index, struct nozomi *dc) goto put; } - tty_buffer_request_room(tty, size); - while (size > 0) { read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); @@ -1473,9 +1471,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, for (i = 0; i < MAX_PORT; i++) { struct device *tty_dev; - - mutex_init(&dc->port[i].tty_sem); - tty_port_init(&dc->port[i].port); + 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, &pdev->dev); @@ -1600,67 +1600,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr) * ---------------------------------------------------------------------------- */ -/* Called when the userspace process opens the tty, /dev/noz*. */ -static int ntty_open(struct tty_struct *tty, struct file *file) +static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) { struct port *port = get_port_by_tty(tty); struct nozomi *dc = get_dc_by_tty(tty); - unsigned long flags; - + int ret; if (!port || !dc || dc->state != NOZOMI_STATE_READY) return -ENODEV; - - if (mutex_lock_interruptible(&port->tty_sem)) - return -ERESTARTSYS; - - port->port.count++; - dc->open_ttys++; - - /* Enable interrupt downlink for channel */ - if (port->port.count == 1) { - tty->driver_data = port; - tty_port_tty_set(&port->port, tty); - DBG1("open: %d", port->token_dl); - spin_lock_irqsave(&dc->spin_mutex, flags); - dc->last_ier = dc->last_ier | port->token_dl; - writew(dc->last_ier, dc->reg_ier); - spin_unlock_irqrestore(&dc->spin_mutex, flags); + ret = tty_init_termios(tty); + if (ret == 0) { + tty_driver_kref_get(driver); + driver->ttys[tty->index] = tty; } - mutex_unlock(&port->tty_sem); - return 0; + return ret; } -/* Called when the userspace process close the tty, /dev/noz*. Also - called immediately if ntty_open fails in which case tty->driver_data - will be NULL an we exit by the first return */ +static void ntty_cleanup(struct tty_struct *tty) +{ + tty->driver_data = NULL; +} -static void ntty_close(struct tty_struct *tty, struct file *file) +static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) { - struct nozomi *dc = get_dc_by_tty(tty); - struct port *nport = tty->driver_data; - struct tty_port *port = &nport->port; + struct port *port = container_of(tport, struct port, port); + struct nozomi *dc = port->dc; unsigned long flags; - if (!dc || !nport) - return; + DBG1("open: %d", port->token_dl); + spin_lock_irqsave(&dc->spin_mutex, flags); + dc->last_ier = dc->last_ier | port->token_dl; + writew(dc->last_ier, dc->reg_ier); + dc->open_ttys++; + spin_unlock_irqrestore(&dc->spin_mutex, flags); + printk("noz: activated %d: %p\n", tty->index, tport); + return 0; +} - /* Users cannot interrupt a close */ - mutex_lock(&nport->tty_sem); +static int ntty_open(struct tty_struct *tty, struct file *filp) +{ + struct port *port = get_port_by_tty(tty); + return tty_port_open(&port->port, tty, filp); +} - WARN_ON(!port->count); +static void ntty_shutdown(struct tty_port *tport) +{ + struct port *port = container_of(tport, struct port, port); + struct nozomi *dc = port->dc; + unsigned long flags; + DBG1("close: %d", port->token_dl); + spin_lock_irqsave(&dc->spin_mutex, flags); + dc->last_ier &= ~(port->token_dl); + writew(dc->last_ier, dc->reg_ier); dc->open_ttys--; - port->count--; + spin_unlock_irqrestore(&dc->spin_mutex, flags); + printk("noz: shutdown %p\n", tport); +} - if (port->count == 0) { - DBG1("close: %d", nport->token_dl); - tty_port_tty_set(port, NULL); - spin_lock_irqsave(&dc->spin_mutex, flags); - dc->last_ier &= ~(nport->token_dl); - writew(dc->last_ier, dc->reg_ier); - spin_unlock_irqrestore(&dc->spin_mutex, flags); - } - mutex_unlock(&nport->tty_sem); +static void ntty_close(struct tty_struct *tty, struct file *filp) +{ + struct port *port = tty->driver_data; + if (port) + tty_port_close(&port->port, tty, filp); +} + +static void ntty_hangup(struct tty_struct *tty) +{ + struct port *port = tty->driver_data; + tty_port_hangup(&port->port); } /* @@ -1680,15 +1687,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, if (!dc || !port) return -ENODEV; - if (unlikely(!mutex_trylock(&port->tty_sem))) { - /* - * must test lock as tty layer wraps calls - * to this function with BKL - */ - dev_err(&dc->pdev->dev, "Would have deadlocked - " - "return EAGAIN\n"); - return -EAGAIN; - } + mutex_lock(&port->tty_sem); if (unlikely(!port->port.count)) { DBG1(" "); @@ -1728,25 +1727,23 @@ exit: * This method is called by the upper tty layer. * #according to sources N_TTY.c it expects a value >= 0 and * does not check for negative values. + * + * If the port is unplugged report lots of room and let the bits + * dribble away so we don't block anything. */ static int ntty_write_room(struct tty_struct *tty) { struct port *port = tty->driver_data; - int room = 0; + int room = 4096; const struct nozomi *dc = get_dc_by_tty(tty); - if (!dc || !port) - return 0; - if (!mutex_trylock(&port->tty_sem)) - return 0; - - if (!port->port.count) - goto exit; - - room = port->fifo_ul.size - kfifo_len(&port->fifo_ul); - -exit: - mutex_unlock(&port->tty_sem); + if (dc) { + mutex_lock(&port->tty_sem); + if (port->port.count) + room = port->fifo_ul.size - + kfifo_len(&port->fifo_ul); + mutex_unlock(&port->tty_sem); + } return room; } @@ -1906,10 +1903,16 @@ exit_in_buffer: return rval; } +static const struct tty_port_operations noz_tty_port_ops = { + .activate = ntty_activate, + .shutdown = ntty_shutdown, +}; + static const struct tty_operations tty_ops = { .ioctl = ntty_ioctl, .open = ntty_open, .close = ntty_close, + .hangup = ntty_hangup, .write = ntty_write, .write_room = ntty_write_room, .unthrottle = ntty_unthrottle, @@ -1917,6 +1920,8 @@ static const struct tty_operations tty_ops = { .chars_in_buffer = ntty_chars_in_buffer, .tiocmget = ntty_tiocmget, .tiocmset = ntty_tiocmset, + .install = ntty_install, + .cleanup = ntty_cleanup, }; /* Module initialization */ diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 452370af95d..986aa606a6b 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -658,8 +658,7 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) info->mon.char_max = char_count; info->mon.char_last = char_count; #endif - len = tty_buffer_request_room(tty, char_count); - while (len--) { + while (char_count--) { data = base_addr[CyRDR]; tty_insert_flip_char(tty, data, TTY_NORMAL); #ifdef CYCLOM_16Y_HACK diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 268e17f9ec3..07ac14d949c 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -646,8 +646,6 @@ static void sx_receive(struct specialix_board *bp) dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); port->hits[count > 8 ? 9 : count]++; - tty_buffer_request_room(tty, count); - while (count--) tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); tty_flip_buffer_push(tty); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 4846b73ef28..0658fc54822 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -2031,7 +2031,7 @@ static int mgsl_put_char(struct tty_struct *tty, unsigned char ch) if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) return 0; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return 0; spin_lock_irqsave(&info->irq_spinlock, flags); @@ -2121,7 +2121,7 @@ static int mgsl_write(struct tty_struct * tty, if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) goto cleanup; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) goto cleanup; if ( info->params.mode == MGSL_MODE_HDLC || diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 8678f0c8699..4561ce2fba6 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -468,7 +468,7 @@ static unsigned int free_tbuf_count(struct slgt_info *info); static unsigned int tbuf_bytes(struct slgt_info *info); static void reset_tbufs(struct slgt_info *info); static void tdma_reset(struct slgt_info *info); -static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); +static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count); static void get_signals(struct slgt_info *info); static void set_signals(struct slgt_info *info); @@ -813,59 +813,32 @@ static int write(struct tty_struct *tty, int ret = 0; struct slgt_info *info = tty->driver_data; unsigned long flags; - unsigned int bufs_needed; if (sanity_check(info, tty->name, "write")) - goto cleanup; + return -EIO; + DBGINFO(("%s write count=%d\n", info->device_name, count)); - if (!info->tx_buf) - goto cleanup; + if (!info->tx_buf || (count > info->max_frame_size)) + return -EIO; - if (count > info->max_frame_size) { - ret = -EIO; - goto cleanup; - } + if (!count || tty->stopped || tty->hw_stopped) + return 0; - if (!count) - goto cleanup; + spin_lock_irqsave(&info->lock, flags); - if (!info->tx_active && in |