diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 11:47:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 11:47:22 -0500 |
commit | 94468080220162f74dc6ce5c3e95e5fec8022902 (patch) | |
tree | b1c46b83e4e731b7b4f70bd341267da519958bdb /drivers/char | |
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/char')
-rw-r--r-- | drivers/char/cyclades.c | 16 | ||||
-rw-r--r-- | drivers/char/hvc_console.c | 2 | ||||
-rw-r--r-- | drivers/char/ip2/ip2main.c | 26 | ||||
-rw-r--r-- | drivers/char/isicom.c | 54 | ||||
-rw-r--r-- | drivers/char/moxa.c | 20 | ||||
-rw-r--r-- | drivers/char/mxser.c | 3 | ||||
-rw-r--r-- | drivers/char/nozomi.c | 157 | ||||
-rw-r--r-- | drivers/char/serial167.c | 3 | ||||
-rw-r--r-- | drivers/char/specialix.c | 2 | ||||
-rw-r--r-- | drivers/char/synclink.c | 4 | ||||
-rw-r--r-- | drivers/char/synclink_gt.c | 186 | ||||
-rw-r--r-- | drivers/char/tty_buffer.c | 6 | ||||
-rw-r--r-- | drivers/char/tty_ldisc.c | 50 | ||||
-rw-r--r-- | drivers/char/vt_ioctl.c | 39 |
14 files changed, 307 insertions, 261 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 4254457d3911..b861c08263a4 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -158,13 +158,11 @@ static unsigned int cy_isa_addresses[] = { | |||
158 | 158 | ||
159 | #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) | 159 | #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) |
160 | 160 | ||
161 | #ifdef MODULE | ||
162 | static long maddr[NR_CARDS]; | 161 | static long maddr[NR_CARDS]; |
163 | static int irq[NR_CARDS]; | 162 | static int irq[NR_CARDS]; |
164 | 163 | ||
165 | module_param_array(maddr, long, NULL, 0); | 164 | module_param_array(maddr, long, NULL, 0); |
166 | module_param_array(irq, int, NULL, 0); | 165 | module_param_array(irq, int, NULL, 0); |
167 | #endif | ||
168 | 166 | ||
169 | #endif /* CONFIG_ISA */ | 167 | #endif /* CONFIG_ISA */ |
170 | 168 | ||
@@ -598,12 +596,6 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, | |||
598 | save_car = readb(base_addr + (CyCAR << index)); | 596 | save_car = readb(base_addr + (CyCAR << index)); |
599 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 597 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
600 | 598 | ||
601 | /* validate the port# (as configured and open) */ | ||
602 | if (channel + chip * 4 >= cinfo->nports) { | ||
603 | cy_writeb(base_addr + (CySRER << index), | ||
604 | readb(base_addr + (CySRER << index)) & ~CyTxRdy); | ||
605 | goto end; | ||
606 | } | ||
607 | info = &cinfo->ports[channel + chip * 4]; | 599 | info = &cinfo->ports[channel + chip * 4]; |
608 | tty = tty_port_tty_get(&info->port); | 600 | tty = tty_port_tty_get(&info->port); |
609 | if (tty == NULL) { | 601 | if (tty == NULL) { |
@@ -3316,13 +3308,10 @@ static int __init cy_detect_isa(void) | |||
3316 | unsigned short cy_isa_irq, nboard; | 3308 | unsigned short cy_isa_irq, nboard; |
3317 | void __iomem *cy_isa_address; | 3309 | void __iomem *cy_isa_address; |
3318 | unsigned short i, j, cy_isa_nchan; | 3310 | unsigned short i, j, cy_isa_nchan; |
3319 | #ifdef MODULE | ||
3320 | int isparam = 0; | 3311 | int isparam = 0; |
3321 | #endif | ||
3322 | 3312 | ||
3323 | nboard = 0; | 3313 | nboard = 0; |
3324 | 3314 | ||
3325 | #ifdef MODULE | ||
3326 | /* Check for module parameters */ | 3315 | /* Check for module parameters */ |
3327 | for (i = 0; i < NR_CARDS; i++) { | 3316 | for (i = 0; i < NR_CARDS; i++) { |
3328 | if (maddr[i] || i) { | 3317 | if (maddr[i] || i) { |
@@ -3332,7 +3321,6 @@ static int __init cy_detect_isa(void) | |||
3332 | if (!maddr[i]) | 3321 | if (!maddr[i]) |
3333 | break; | 3322 | break; |
3334 | } | 3323 | } |
3335 | #endif | ||
3336 | 3324 | ||
3337 | /* scan the address table probing for Cyclom-Y/ISA boards */ | 3325 | /* scan the address table probing for Cyclom-Y/ISA boards */ |
3338 | for (i = 0; i < NR_ISA_ADDRS; i++) { | 3326 | for (i = 0; i < NR_ISA_ADDRS; i++) { |
@@ -3353,11 +3341,10 @@ static int __init cy_detect_isa(void) | |||
3353 | iounmap(cy_isa_address); | 3341 | iounmap(cy_isa_address); |
3354 | continue; | 3342 | continue; |
3355 | } | 3343 | } |
3356 | #ifdef MODULE | 3344 | |
3357 | if (isparam && i < NR_CARDS && irq[i]) | 3345 | if (isparam && i < NR_CARDS && irq[i]) |
3358 | cy_isa_irq = irq[i]; | 3346 | cy_isa_irq = irq[i]; |
3359 | else | 3347 | else |
3360 | #endif | ||
3361 | /* find out the board's irq by probing */ | 3348 | /* find out the board's irq by probing */ |
3362 | cy_isa_irq = detect_isa_irq(cy_isa_address); | 3349 | cy_isa_irq = detect_isa_irq(cy_isa_address); |
3363 | if (cy_isa_irq == 0) { | 3350 | if (cy_isa_irq == 0) { |
@@ -4208,3 +4195,4 @@ module_exit(cy_cleanup_module); | |||
4208 | MODULE_LICENSE("GPL"); | 4195 | MODULE_LICENSE("GPL"); |
4209 | MODULE_VERSION(CY_VERSION); | 4196 | MODULE_VERSION(CY_VERSION); |
4210 | MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); | 4197 | MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); |
4198 | MODULE_FIRMWARE("cyzfirm.bin"); | ||
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 4c3b59be286a..465185fc0f52 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, | |||
146 | return; | 146 | return; |
147 | 147 | ||
148 | /* This console adapter was removed so it is not usable. */ | 148 | /* This console adapter was removed so it is not usable. */ |
149 | if (vtermnos[index] < 0) | 149 | if (vtermnos[index] == -1) |
150 | return; | 150 | return; |
151 | 151 | ||
152 | while (count > 0 || i > 0) { | 152 | while (count > 0 || i > 0) { |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 517271c762e6..911e1da6def2 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -208,6 +208,7 @@ static int DumpFifoBuffer( char __user *, int); | |||
208 | 208 | ||
209 | static void ip2_init_board(int, const struct firmware *); | 209 | static void ip2_init_board(int, const struct firmware *); |
210 | static unsigned short find_eisa_board(int); | 210 | static unsigned short find_eisa_board(int); |
211 | static int ip2_setup(char *str); | ||
211 | 212 | ||
212 | /***************/ | 213 | /***************/ |
213 | /* Static Data */ | 214 | /* Static Data */ |
@@ -263,7 +264,7 @@ static int tracewrap; | |||
263 | /* Macros */ | 264 | /* Macros */ |
264 | /**********/ | 265 | /**********/ |
265 | 266 | ||
266 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) | 267 | #ifdef IP2DEBUG_OPEN |
267 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ | 268 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ |
268 | tty->name,(pCh->flags), \ | 269 | tty->name,(pCh->flags), \ |
269 | tty->count,/*GET_USE_COUNT(module)*/0,s) | 270 | tty->count,/*GET_USE_COUNT(module)*/0,s) |
@@ -285,7 +286,10 @@ MODULE_AUTHOR("Doug McNash"); | |||
285 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | 286 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); |
286 | MODULE_LICENSE("GPL"); | 287 | MODULE_LICENSE("GPL"); |
287 | 288 | ||
289 | #define MAX_CMD_STR 50 | ||
290 | |||
288 | static int poll_only; | 291 | static int poll_only; |
292 | static char cmd[MAX_CMD_STR]; | ||
289 | 293 | ||
290 | static int Eisa_irq; | 294 | static int Eisa_irq; |
291 | static int Eisa_slot; | 295 | static int Eisa_slot; |
@@ -309,6 +313,8 @@ module_param_array(io, int, NULL, 0); | |||
309 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); | 313 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); |
310 | module_param(poll_only, bool, 0); | 314 | module_param(poll_only, bool, 0); |
311 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); | 315 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); |
316 | module_param_string(ip2, cmd, MAX_CMD_STR, 0); | ||
317 | MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); | ||
312 | 318 | ||
313 | /* for sysfs class support */ | 319 | /* for sysfs class support */ |
314 | static struct class *ip2_class; | 320 | static struct class *ip2_class; |
@@ -487,7 +493,6 @@ static const struct firmware *ip2_request_firmware(void) | |||
487 | return fw; | 493 | return fw; |
488 | } | 494 | } |
489 | 495 | ||
490 | #ifndef MODULE | ||
491 | /****************************************************************************** | 496 | /****************************************************************************** |
492 | * ip2_setup: | 497 | * ip2_setup: |
493 | * str: kernel command line string | 498 | * str: kernel command line string |
@@ -531,7 +536,6 @@ static int __init ip2_setup(char *str) | |||
531 | return 1; | 536 | return 1; |
532 | } | 537 | } |
533 | __setup("ip2=", ip2_setup); | 538 | __setup("ip2=", ip2_setup); |
534 | #endif /* !MODULE */ | ||
535 | 539 | ||
536 | static int __init ip2_loadmain(void) | 540 | static int __init ip2_loadmain(void) |
537 | { | 541 | { |
@@ -539,14 +543,20 @@ static int __init ip2_loadmain(void) | |||
539 | int err = 0; | 543 | int err = 0; |
540 | i2eBordStrPtr pB = NULL; | 544 | i2eBordStrPtr pB = NULL; |
541 | int rc = -1; | 545 | int rc = -1; |
542 | struct pci_dev *pdev = NULL; | ||
543 | const struct firmware *fw = NULL; | 546 | const struct firmware *fw = NULL; |
547 | char *str; | ||
548 | |||
549 | str = cmd; | ||
544 | 550 | ||
545 | if (poll_only) { | 551 | if (poll_only) { |
546 | /* Hard lock the interrupts to zero */ | 552 | /* Hard lock the interrupts to zero */ |
547 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; | 553 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; |
548 | } | 554 | } |
549 | 555 | ||
556 | /* Check module parameter with 'ip2=' has been passed or not */ | ||
557 | if (!poll_only && (!strncmp(str, "ip2=", 4))) | ||
558 | ip2_setup(str); | ||
559 | |||
550 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); | 560 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); |
551 | 561 | ||
552 | /* process command line arguments to modprobe or | 562 | /* process command line arguments to modprobe or |
@@ -612,6 +622,7 @@ static int __init ip2_loadmain(void) | |||
612 | case PCI: | 622 | case PCI: |
613 | #ifdef CONFIG_PCI | 623 | #ifdef CONFIG_PCI |
614 | { | 624 | { |
625 | struct pci_dev *pdev = NULL; | ||
615 | u32 addr; | 626 | u32 addr; |
616 | int status; | 627 | int status; |
617 | 628 | ||
@@ -626,7 +637,7 @@ static int __init ip2_loadmain(void) | |||
626 | 637 | ||
627 | if (pci_enable_device(pdev)) { | 638 | if (pci_enable_device(pdev)) { |
628 | dev_err(&pdev->dev, "can't enable device\n"); | 639 | dev_err(&pdev->dev, "can't enable device\n"); |
629 | break; | 640 | goto out; |
630 | } | 641 | } |
631 | ip2config.type[i] = PCI; | 642 | ip2config.type[i] = PCI; |
632 | ip2config.pci_dev[i] = pci_dev_get(pdev); | 643 | ip2config.pci_dev[i] = pci_dev_get(pdev); |
@@ -638,6 +649,8 @@ static int __init ip2_loadmain(void) | |||
638 | dev_err(&pdev->dev, "I/O address error\n"); | 649 | dev_err(&pdev->dev, "I/O address error\n"); |
639 | 650 | ||
640 | ip2config.irq[i] = pdev->irq; | 651 | ip2config.irq[i] = pdev->irq; |
652 | out: | ||
653 | pci_dev_put(pdev); | ||
641 | } | 654 | } |
642 | #else | 655 | #else |
643 | printk(KERN_ERR "IP2: PCI card specified but PCI " | 656 | printk(KERN_ERR "IP2: PCI card specified but PCI " |
@@ -656,7 +669,6 @@ static int __init ip2_loadmain(void) | |||
656 | break; | 669 | break; |
657 | } /* switch */ | 670 | } /* switch */ |
658 | } /* for */ | 671 | } /* for */ |
659 | pci_dev_put(pdev); | ||
660 | 672 | ||
661 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | 673 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
662 | if (ip2config.addr[i]) { | 674 | if (ip2config.addr[i]) { |
@@ -3197,3 +3209,5 @@ static struct pci_device_id ip2main_pci_tbl[] __devinitdata = { | |||
3197 | }; | 3209 | }; |
3198 | 3210 | ||
3199 | MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); | 3211 | MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); |
3212 | |||
3213 | MODULE_FIRMWARE("intelliport2.bin"); | ||
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 300d5bd6cd06..be2e8f9a27c3 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -113,6 +113,8 @@ | |||
113 | * 64-bit verification | 113 | * 64-bit verification |
114 | */ | 114 | */ |
115 | 115 | ||
116 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
117 | |||
116 | #include <linux/module.h> | 118 | #include <linux/module.h> |
117 | #include <linux/firmware.h> | 119 | #include <linux/firmware.h> |
118 | #include <linux/kernel.h> | 120 | #include <linux/kernel.h> |
@@ -140,7 +142,6 @@ | |||
140 | #define InterruptTheCard(base) outw(0, (base) + 0xc) | 142 | #define InterruptTheCard(base) outw(0, (base) + 0xc) |
141 | #define ClearInterrupt(base) inw((base) + 0x0a) | 143 | #define ClearInterrupt(base) inw((base) + 0x0a) |
142 | 144 | ||
143 | #define pr_dbg(str...) pr_debug("ISICOM: " str) | ||
144 | #ifdef DEBUG | 145 | #ifdef DEBUG |
145 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) | 146 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) |
146 | #else | 147 | #else |
@@ -249,8 +250,7 @@ static int lock_card(struct isi_board *card) | |||
249 | spin_unlock_irqrestore(&card->card_lock, card->flags); | 250 | spin_unlock_irqrestore(&card->card_lock, card->flags); |
250 | msleep(10); | 251 | msleep(10); |
251 | } | 252 | } |
252 | printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n", | 253 | pr_warning("Failed to lock Card (0x%lx)\n", card->base); |
253 | card->base); | ||
254 | 254 | ||
255 | return 0; /* Failed to acquire the card! */ | 255 | return 0; /* Failed to acquire the card! */ |
256 | } | 256 | } |
@@ -379,13 +379,13 @@ static inline int __isicom_paranoia_check(struct isi_port const *port, | |||
379 | char *name, const char *routine) | 379 | char *name, const char *routine) |
380 | { | 380 | { |
381 | if (!port) { | 381 | if (!port) { |
382 | printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for " | 382 | pr_warning("Warning: bad isicom magic for dev %s in %s.\n", |
383 | "dev %s in %s.\n", name, routine); | 383 | name, routine); |
384 | return 1; | 384 | return 1; |
385 | } | 385 | } |
386 | if (port->magic != ISICOM_MAGIC) { | 386 | if (port->magic != ISICOM_MAGIC) { |
387 | printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for " | 387 | pr_warning("Warning: NULL isicom port for dev %s in %s.\n", |
388 | "dev %s in %s.\n", name, routine); | 388 | name, routine); |
389 | return 1; | 389 | return 1; |
390 | } | 390 | } |
391 | 391 | ||
@@ -450,8 +450,8 @@ static void isicom_tx(unsigned long _data) | |||
450 | if (!(inw(base + 0x02) & (1 << port->channel))) | 450 | if (!(inw(base + 0x02) & (1 << port->channel))) |
451 | continue; | 451 | continue; |
452 | 452 | ||
453 | pr_dbg("txing %d bytes, port%d.\n", txcount, | 453 | pr_debug("txing %d bytes, port%d.\n", |
454 | port->channel + 1); | 454 | txcount, port->channel + 1); |
455 | outw((port->channel << isi_card[card].shift_count) | txcount, | 455 | outw((port->channel << isi_card[card].shift_count) | txcount, |
456 | base); | 456 | base); |
457 | residue = NO; | 457 | residue = NO; |
@@ -547,8 +547,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
547 | byte_count = header & 0xff; | 547 | byte_count = header & 0xff; |
548 | 548 | ||
549 | if (channel + 1 > card->port_count) { | 549 | if (channel + 1 > card->port_count) { |
550 | printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): " | 550 | pr_warning("%s(0x%lx): %d(channel) > port_count.\n", |
551 | "%d(channel) > port_count.\n", base, channel+1); | 551 | __func__, base, channel+1); |
552 | outw(0x0000, base+0x04); /* enable interrupts */ | 552 | outw(0x0000, base+0x04); /* enable interrupts */ |
553 | spin_unlock(&card->card_lock); | 553 | spin_unlock(&card->card_lock); |
554 | return IRQ_HANDLED; | 554 | return IRQ_HANDLED; |
@@ -582,14 +582,15 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
582 | if (port->status & ISI_DCD) { | 582 | if (port->status & ISI_DCD) { |
583 | if (!(header & ISI_DCD)) { | 583 | if (!(header & ISI_DCD)) { |
584 | /* Carrier has been lost */ | 584 | /* Carrier has been lost */ |
585 | pr_dbg("interrupt: DCD->low.\n" | 585 | pr_debug("%s: DCD->low.\n", |
586 | ); | 586 | __func__); |
587 | port->status &= ~ISI_DCD; | 587 | port->status &= ~ISI_DCD; |
588 | tty_hangup(tty); | 588 | tty_hangup(tty); |
589 | } | 589 | } |
590 | } else if (header & ISI_DCD) { | 590 | } else if (header & ISI_DCD) { |
591 | /* Carrier has been detected */ | 591 | /* Carrier has been detected */ |
592 | pr_dbg("interrupt: DCD->high.\n"); | 592 | pr_debug("%s: DCD->high.\n", |
593 | __func__); | ||
593 | port->status |= ISI_DCD; | 594 | port->status |= ISI_DCD; |
594 | wake_up_interruptible(&port->port.open_wait); | 595 | wake_up_interruptible(&port->port.open_wait); |
595 | } | 596 | } |
@@ -641,17 +642,19 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
641 | break; | 642 | break; |
642 | 643 | ||
643 | case 2: /* Statistics */ | 644 | case 2: /* Statistics */ |
644 | pr_dbg("isicom_interrupt: stats!!!.\n"); | 645 | pr_debug("%s: stats!!!\n", __func__); |
645 | break; | 646 | break; |
646 | 647 | ||
647 | default: | 648 | default: |
648 | pr_dbg("Intr: Unknown code in status packet.\n"); | 649 | pr_debug("%s: Unknown code in status packet.\n", |
650 | __func__); | ||
649 | break; | 651 | break; |
650 | } | 652 | } |
651 | } else { /* Data Packet */ | 653 | } else { /* Data Packet */ |
652 | 654 | ||
653 | count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); | 655 | count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); |
654 | pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count); | 656 | pr_debug("%s: Can rx %d of %d bytes.\n", |
657 | __func__, count, byte_count); | ||
655 | word_count = count >> 1; | 658 | word_count = count >> 1; |
656 | insw(base, rp, word_count); | 659 | insw(base, rp, word_count); |
657 | byte_count -= (word_count << 1); | 660 | byte_count -= (word_count << 1); |
@@ -661,8 +664,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
661 | byte_count -= 2; | 664 | byte_count -= 2; |
662 | } | 665 | } |
663 | if (byte_count > 0) { | 666 | if (byte_count > 0) { |
664 | pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping " | 667 | pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n", |
665 | "bytes...\n", base, channel + 1); | 668 | __func__, base, channel + 1); |
666 | /* drain out unread xtra data */ | 669 | /* drain out unread xtra data */ |
667 | while (byte_count > 0) { | 670 | while (byte_count > 0) { |
668 | inw(base); | 671 | inw(base); |
@@ -888,8 +891,8 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
888 | struct isi_board *card = port->card; | 891 | struct isi_board *card = port->card; |
889 | 892 | ||
890 | if (--card->count < 0) { | 893 | if (--card->count < 0) { |
891 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 894 | pr_debug("%s: bad board(0x%lx) count %d.\n", |
892 | card->base, card->count); | 895 | __func__, card->base, card->count); |
893 | card->count = 0; | 896 | card->count = 0; |
894 | } | 897 | } |
895 | /* last port was closed, shutdown that board too */ | 898 | /* last port was closed, shutdown that board too */ |
@@ -1681,13 +1684,13 @@ static int __init isicom_init(void) | |||
1681 | 1684 | ||
1682 | retval = tty_register_driver(isicom_normal); | 1685 | retval = tty_register_driver(isicom_normal); |
1683 | if (retval) { | 1686 | if (retval) { |
1684 | pr_dbg("Couldn't register the dialin driver\n"); | 1687 | pr_debug("Couldn't register the dialin driver\n"); |
1685 | goto err_puttty; | 1688 | goto err_puttty; |
1686 | } | 1689 | } |
1687 | 1690 | ||
1688 | retval = pci_register_driver(&isicom_driver); | 1691 | retval = pci_register_driver(&isicom_driver); |
1689 | if (retval < 0) { | 1692 | if (retval < 0) { |
1690 | printk(KERN_ERR "ISICOM: Unable to register pci driver.\n"); | 1693 | pr_err("Unable to register pci driver.\n"); |
1691 | goto err_unrtty; | 1694 | goto err_unrtty; |
1692 | } | 1695 | } |
1693 | 1696 | ||
@@ -1717,3 +1720,8 @@ module_exit(isicom_exit); | |||
1717 | MODULE_AUTHOR("MultiTech"); | 1720 | MODULE_AUTHOR("MultiTech"); |
1718 | MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); | 1721 | MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); |
1719 | MODULE_LICENSE("GPL"); | 1722 | MODULE_LICENSE("GPL"); |
1723 | MODULE_FIRMWARE("isi608.bin"); | ||
1724 | MODULE_FIRMWARE("isi608em.bin"); | ||
1725 | MODULE_FIRMWARE("isi616em.bin"); | ||
1726 | MODULE_FIRMWARE("isi4608.bin"); | ||
1727 | MODULE_FIRMWARE("isi4616.bin"); | ||
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 63ee3bbc1ce4..166495d6a1d7 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -164,24 +164,25 @@ static unsigned int moxaFuncTout = HZ / 2; | |||
164 | static unsigned int moxaLowWaterChk; | 164 | static unsigned int moxaLowWaterChk; |
165 | static DEFINE_MUTEX(moxa_openlock); | 165 | static DEFINE_MUTEX(moxa_openlock); |
166 | static DEFINE_SPINLOCK(moxa_lock); | 166 | static DEFINE_SPINLOCK(moxa_lock); |
167 | /* Variables for insmod */ | 167 | |
168 | #ifdef MODULE | ||
169 | static unsigned long baseaddr[MAX_BOARDS]; | 168 | static unsigned long baseaddr[MAX_BOARDS]; |
170 | static unsigned int type[MAX_BOARDS]; | 169 | static unsigned int type[MAX_BOARDS]; |
171 | static unsigned int numports[MAX_BOARDS]; | 170 | static unsigned int numports[MAX_BOARDS]; |
172 | #endif | ||
173 | 171 | ||
174 | MODULE_AUTHOR("William Chen"); | 172 | MODULE_AUTHOR("William Chen"); |
175 | MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); | 173 | MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); |
176 | MODULE_LICENSE("GPL"); | 174 | MODULE_LICENSE("GPL"); |
177 | #ifdef MODULE | 175 | MODULE_FIRMWARE("c218tunx.cod"); |
176 | MODULE_FIRMWARE("cp204unx.cod"); | ||
177 | MODULE_FIRMWARE("c320tunx.cod"); | ||
178 | |||
178 | module_param_array(type, uint, NULL, 0); | 179 | module_param_array(type, uint, NULL, 0); |
179 | MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); | 180 | MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); |
180 | module_param_array(baseaddr, ulong, NULL, 0); | 181 | module_param_array(baseaddr, ulong, NULL, 0); |
181 | MODULE_PARM_DESC(baseaddr, "base address"); | 182 | MODULE_PARM_DESC(baseaddr, "base address"); |
182 | module_param_array(numports, uint, NULL, 0); | 183 | module_param_array(numports, uint, NULL, 0); |
183 | MODULE_PARM_DESC(numports, "numports (ignored for C218)"); | 184 | MODULE_PARM_DESC(numports, "numports (ignored for C218)"); |
184 | #endif | 185 | |
185 | module_param(ttymajor, int, 0); | 186 | module_param(ttymajor, int, 0); |
186 | 187 | ||
187 | /* | 188 | /* |
@@ -1024,6 +1025,8 @@ static int __init moxa_init(void) | |||
1024 | { | 1025 | { |
1025 | unsigned int isabrds = 0; | 1026 | unsigned int isabrds = 0; |
1026 | int retval = 0; | 1027 | int retval = 0; |
1028 | struct moxa_board_conf *brd = moxa_boards; | ||
1029 | unsigned int i; | ||
1027 | 1030 | ||
1028 | printk(KERN_INFO "MOXA Intellio family driver version %s\n", | 1031 | printk(KERN_INFO "MOXA Intellio family driver version %s\n", |
1029 | MOXA_VERSION); | 1032 | MOXA_VERSION); |
@@ -1051,10 +1054,7 @@ static int __init moxa_init(void) | |||
1051 | } | 1054 | } |
1052 | 1055 | ||
1053 | /* Find the boards defined from module args. */ | 1056 | /* Find the boards defined from module args. */ |
1054 | #ifdef MODULE | 1057 | |
1055 | { | ||
1056 | struct moxa_board_conf *brd = moxa_boards; | ||
1057 | unsigned int i; | ||
1058 | for (i = 0; i < MAX_BOARDS; i++) { | 1058 | for (i = 0; i < MAX_BOARDS; i++) { |
1059 | if (!baseaddr[i]) | 1059 | if (!baseaddr[i]) |
1060 | break; | 1060 | break; |
@@ -1087,8 +1087,6 @@ static int __init moxa_init(void) | |||
1087 | isabrds++; | 1087 | isabrds++; |
1088 | } | 1088 | } |
1089 | } | 1089 | } |
1090 | } | ||
1091 | #endif | ||
1092 | 1090 | ||
1093 | #ifdef CONFIG_PCI | 1091 | #ifdef CONFIG_PCI |
1094 | retval = pci_register_driver(&moxa_pci_driver); | 1092 | retval = pci_register_driver(&moxa_pci_driver); |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3d923065d9a2..e0c5d2a69046 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) | |||
895 | if (inb(info->ioaddr + UART_LSR) == 0xff) { | 895 | if (inb(info->ioaddr + UART_LSR) == 0xff) { |
896 | spin_unlock_irqrestore(&info->slock, flags); | 896 | spin_unlock_irqrestore(&info->slock, flags); |
897 | if (capable(CAP_SYS_ADMIN)) { | 897 | if (capable(CAP_SYS_ADMIN)) { |
898 | if (tty) | 898 | set_bit(TTY_IO_ERROR, &tty->flags); |
899 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
900 | return 0; | 899 | return 0; |
901 | } else | 900 | } else |
902 | return -ENODEV; | 901 | return -ENODEV; |
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 2ad7d37afbd0..a3f32a15fde4 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -136,10 +136,6 @@ static int debug; | |||
136 | #define RECEIVE_BUF_MAX 4 | 136 | #define RECEIVE_BUF_MAX 4 |
137 | 137 | ||
138 | 138 | ||
139 | /* Define all types of vendors and devices to support */ | ||
140 | #define VENDOR1 0x1931 /* Vendor Option */ | ||
141 | #define DEVICE1 0x000c /* HSDPA card */ | ||
142 | |||
143 | #define R_IIR 0x0000 /* Interrupt Identity Register */ | 139 | #define R_IIR 0x0000 /* Interrupt Identity Register */ |
144 | #define R_FCR 0x0000 /* Flow Control Register */ | 140 | #define R_FCR 0x0000 /* Flow Control Register */ |
145 | #define R_IER 0x0004 /* Interrupt Enable Register */ | 141 | #define R_IER 0x0004 /* Interrupt Enable Register */ |
@@ -371,6 +367,8 @@ struct port { | |||
371 | struct mutex tty_sem; | 367 | struct mutex tty_sem; |
372 | wait_queue_head_t tty_wait; | 368 | wait_queue_head_t tty_wait; |
373 | struct async_icount tty_icount; | 369 | struct async_icount tty_icount; |
370 | |||
371 | struct nozomi *dc; | ||
374 | }; | 372 | }; |
375 | 373 | ||
376 | /* Private data one for each card in the system */ | 374 | /* Private data one for each card in the system */ |
@@ -405,7 +403,7 @@ struct buffer { | |||
405 | 403 | ||
406 | /* Global variables */ | 404 | /* Global variables */ |
407 | static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { | 405 | static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { |
408 | {PCI_DEVICE(VENDOR1, DEVICE1)}, | 406 | {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ |
409 | {}, | 407 | {}, |
410 | }; | 408 | }; |
411 | 409 | ||
@@ -414,6 +412,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); | |||
414 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; | 412 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; |
415 | static struct tty_driver *ntty_driver; | 413 | static struct tty_driver *ntty_driver; |
416 | 414 | ||
415 | static const struct tty_port_operations noz_tty_port_ops; | ||
416 | |||
417 | /* | 417 | /* |
418 | * find card by tty_index | 418 | * find card by tty_index |
419 | */ | 419 | */ |
@@ -853,8 +853,6 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
853 | goto put; | 853 | goto put; |
854 | } | 854 | } |
855 | 855 | ||
856 | tty_buffer_request_room(tty, size); | ||
857 | |||
858 | while (size > 0) { | 856 | while (size > 0) { |
859 | read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); | 857 | read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); |
860 | 858 | ||
@@ -1473,9 +1471,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1473 | 1471 | ||
1474 | for (i = 0; i < MAX_PORT; i++) { | 1472 | for (i = 0; i < MAX_PORT; i++) { |
1475 | struct device *tty_dev; | 1473 | struct device *tty_dev; |
1476 | 1474 | struct port *port = &dc->port[i]; | |
1477 | mutex_init(&dc->port[i].tty_sem); | 1475 | port->dc = dc; |
1478 | tty_port_init(&dc->port[i].port); | 1476 | mutex_init(&port->tty_sem); |
1477 | tty_port_init(&port->port); | ||
1478 | port->port.ops = &noz_tty_port_ops; | ||
1479 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, | 1479 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, |
1480 | &pdev->dev); | 1480 | &pdev->dev); |
1481 | 1481 | ||
@@ -1600,67 +1600,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr) | |||
1600 | * ---------------------------------------------------------------------------- | 1600 | * ---------------------------------------------------------------------------- |
1601 | */ | 1601 | */ |
1602 | 1602 | ||
1603 | /* Called when the userspace process opens the tty, /dev/noz*. */ | 1603 | static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) |
1604 | static int ntty_open(struct tty_struct *tty, struct file *file) | ||
1605 | { | 1604 | { |
1606 | struct port *port = get_port_by_tty(tty); | 1605 | struct port *port = get_port_by_tty(tty); |
1607 | struct nozomi *dc = get_dc_by_tty(tty); | 1606 | struct nozomi *dc = get_dc_by_tty(tty); |
1608 | unsigned long flags; | 1607 | int ret; |
1609 | |||
1610 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) | 1608 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) |
1611 | return -ENODEV; | 1609 | return -ENODEV; |
1612 | 1610 | ret = tty_init_termios(tty); | |
1613 | if (mutex_lock_interruptible(&port->tty_sem)) | 1611 | if (ret == 0) { |
1614 | return -ERESTARTSYS; | 1612 | tty_driver_kref_get(driver); |
1615 | 1613 | driver->ttys[tty->index] = tty; | |
1616 | port->port.count++; | ||
1617 | dc->open_ttys++; | ||
1618 | |||
1619 | /* Enable interrupt downlink for channel */ | ||
1620 | if (port->port.count == 1) { | ||
1621 | tty->driver_data = port; | ||
1622 | tty_port_tty_set(&port->port, tty); | ||
1623 | DBG1("open: %d", port->token_dl); | ||
1624 | spin_lock_irqsave(&dc->spin_mutex, flags); | ||
1625 | dc->last_ier = dc->last_ier | port->token_dl; | ||
1626 | writew(dc->last_ier, dc->reg_ier); | ||
1627 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | ||
1628 | } | 1614 | } |
1629 | mutex_unlock(&port->tty_sem); | 1615 | return ret; |
1630 | return 0; | ||
1631 | } | 1616 | } |
1632 | 1617 | ||
1633 | /* Called when the userspace process close the tty, /dev/noz*. Also | 1618 | static void ntty_cleanup(struct tty_struct *tty) |
1634 | called immediately if ntty_open fails in which case tty->driver_data | 1619 | { |
1635 | will be NULL an we exit by the first return */ | 1620 | tty->driver_data = NULL; |
1621 | } | ||
1636 | 1622 | ||
1637 | static void ntty_close(struct tty_struct *tty, struct file *file) | 1623 | static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) |
1638 | { | 1624 | { |
1639 | struct nozomi *dc = get_dc_by_tty(tty); | 1625 | struct port *port = container_of(tport, struct port, port); |
1640 | struct port *nport = tty->driver_data; | 1626 | struct nozomi *dc = port->dc; |
1641 | struct tty_port *port = &nport->port; | ||
1642 | unsigned long flags; | 1627 | unsigned long flags; |
1643 | 1628 | ||
1644 | if (!dc || !nport) | 1629 | DBG1("open: %d", port->token_dl); |
1645 | return; | 1630 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1631 | dc->last_ier = dc->last_ier | port->token_dl; | ||
1632 | writew(dc->last_ier, dc->reg_ier); | ||
1633 | dc->open_ttys++; | ||
1634 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | ||
1635 | printk("noz: activated %d: %p\n", tty->index, tport); | ||
1636 | return 0; | ||
1637 | } | ||
1646 | 1638 | ||
1647 | /* Users cannot interrupt a close */ | 1639 | static int ntty_open(struct tty_struct *tty, struct file *filp) |
1648 | mutex_lock(&nport->tty_sem); | 1640 | { |
1641 | struct port *port = get_port_by_tty(tty); | ||
1642 | return tty_port_open(&port->port, tty, filp); | ||
1643 | } | ||
1649 | 1644 | ||
1650 | WARN_ON(!port->count); | 1645 | static void ntty_shutdown(struct tty_port *tport) |
1646 | { | ||
1647 | struct port *port = container_of(tport, struct port, port); | ||
1648 | struct nozomi *dc = port->dc; | ||
1649 | unsigned long flags; | ||
1651 | 1650 | ||
1651 | DBG1("close: %d", port->token_dl); | ||
1652 | spin_lock_irqsave(&dc->spin_mutex, flags); | ||
1653 | dc->last_ier &= ~(port->token_dl); | ||
1654 | writew(dc->last_ier, dc->reg_ier); | ||
1652 | dc->open_ttys--; | 1655 | dc->open_ttys--; |
1653 | port->count--; | 1656 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1657 | printk("noz: shutdown %p\n", tport); | ||
1658 | } | ||
1654 | 1659 | ||
1655 | if (port->count == 0) { | 1660 | static void ntty_close(struct tty_struct *tty, struct file *filp) |
1656 | DBG1("close: %d", nport->token_dl); | 1661 | { |
1657 | tty_port_tty_set(port, NULL); | 1662 | struct port *port = tty->driver_data; |
1658 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1663 | if (port) |
1659 | dc->last_ier &= ~(nport->token_dl); | 1664 | tty_port_close(&port->port, tty, filp); |
1660 | writew(dc->last_ier, dc->reg_ier); | 1665 | } |
1661 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1666 | |
1662 | } | 1667 | static void ntty_hangup(struct tty_struct *tty) |
1663 | mutex_unlock(&nport->tty_sem); | 1668 | { |
1669 | struct port *port = tty->driver_data; | ||
1670 | tty_port_hangup(&port->port); | ||
1664 | } | 1671 | } |
1665 | 1672 | ||
1666 | /* | 1673 | /* |
@@ -1680,15 +1687,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, | |||
1680 | if (!dc || !port) | 1687 | if (!dc || !port) |
1681 | return -ENODEV; | 1688 | return -ENODEV; |
1682 | 1689 | ||
1683 | if (unlikely(!mutex_trylock(&port->tty_sem))) { | 1690 | mutex_lock(&port->tty_sem); |
1684 | /* | ||
1685 | * must test lock as tty layer wraps calls | ||
1686 | * to this function with BKL | ||
1687 | */ | ||
1688 | dev_err(&dc->pdev->dev, "Would have deadlocked - " | ||
1689 | "return EAGAIN\n"); | ||
1690 | return -EAGAIN; | ||
1691 | } | ||
1692 | 1691 | ||
1693 | if (unlikely(!port->port.count)) { | 1692 | if (unlikely(!port->port.count)) { |
1694 | DBG1(" "); | 1693 | DBG1(" "); |
@@ -1728,25 +1727,23 @@ exit: | |||
1728 | * This method is called by the upper tty layer. | 1727 | * This method is called by the upper tty layer. |
1729 | * #according to sources N_TTY.c it expects a value >= 0 and | 1728 | * #according to sources N_TTY.c it expects a value >= 0 and |
1730 | * does not check for negative values. | 1729 | * does not check for negative values. |
1730 | * | ||
1731 | * If the port is unplugged report lots of room and let the bits | ||
1732 | * dribble away so we don't block anything. | ||
1731 | */ | 1733 | */ |
1732 | static int ntty_write_room(struct tty_struct *tty) | 1734 | static int ntty_write_room(struct tty_struct *tty) |
1733 | { | 1735 | { |
1734 | struct port *port = tty->driver_data; | 1736 | struct port *port = tty->driver_data; |
1735 | int room = 0; | 1737 | int room = 4096; |
1736 | const struct nozomi *dc = get_dc_by_tty(tty); | 1738 | const struct nozomi *dc = get_dc_by_tty(tty); |
1737 | 1739 | ||
1738 | if (!dc || !port) | 1740 | if (dc) { |
1739 | return 0; | 1741 | mutex_lock(&port->tty_sem); |
1740 | if (!mutex_trylock(&port->tty_sem)) | 1742 | if (port->port.count) |
1741 | return 0; | 1743 | room = port->fifo_ul.size - |
1742 | 1744 | kfifo_len(&port->fifo_ul); | |
1743 | if (!port->port.count) | 1745 | mutex_unlock(&port->tty_sem); |
1744 | goto exit; | 1746 | } |
1745 | |||
1746 | room = port->fifo_ul.size - kfifo_len(&port->fifo_ul); | ||
1747 | |||
1748 | exit: | ||
1749 | mutex_unlock(&port->tty_sem); | ||
1750 | return room; | 1747 | return room; |
1751 | } | 1748 | } |
1752 | 1749 | ||
@@ -1906,10 +1903,16 @@ exit_in_buffer: | |||
1906 | return rval; | 1903 | return rval; |
1907 | } | 1904 | } |
1908 | 1905 | ||
1906 | static const struct tty_port_operations noz_tty_port_ops = { | ||
1907 | .activate = ntty_activate, | ||
1908 | .shutdown = ntty_shutdown, | ||
1909 | }; | ||
1910 | |||
1909 | static const struct tty_operations tty_ops = { | 1911 | static const struct tty_operations tty_ops = { |
1910 | .ioctl = ntty_ioctl, | 1912 | .ioctl = ntty_ioctl, |
1911 | .open = ntty_open, | 1913 | .open = ntty_open, |
1912 | .close = ntty_close, | 1914 | .close = ntty_close, |
1915 | .hangup = ntty_hangup, | ||
1913 | .write = ntty_write, | 1916 | .write = ntty_write, |
1914 | .write_room = ntty_write_room, | 1917 | .write_room = ntty_write_room, |
1915 | .unthrottle = ntty_unthrottle, | 1918 | .unthrottle = ntty_unthrottle, |
@@ -1917,6 +1920,8 @@ static const struct tty_operations tty_ops = { | |||
1917 | .chars_in_buffer = ntty_chars_in_buffer, | 1920 | .chars_in_buffer = ntty_chars_in_buffer, |
1918 | .tiocmget = ntty_tiocmget, | 1921 | .tiocmget = ntty_tiocmget, |
1919 | .tiocmset = ntty_tiocmset, | 1922 | .tiocmset = ntty_tiocmset, |
1923 | .install = ntty_install, | ||
1924 | .cleanup = ntty_cleanup, | ||
1920 | }; | 1925 | }; |
1921 | 1926 | ||
1922 | /* Module initialization */ | 1927 | /* Module initialization */ |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 452370af95de..986aa606a6b6 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) | |||
658 | info->mon.char_max = char_count; | 658 | info->mon.char_max = char_count; |
659 | info->mon.char_last = char_count; | 659 | info->mon.char_last = char_count; |
660 | #endif | 660 | #endif |
661 | len = tty_buffer_request_room(tty, char_count); | 661 | while (char_count--) { |
662 | while (len--) { | ||
663 | data = base_addr[CyRDR]; | 662 | data = base_addr[CyRDR]; |
664 | tty_insert_flip_char(tty, data, TTY_NORMAL); | 663 | tty_insert_flip_char(tty, data, TTY_NORMAL); |
665 | #ifdef CYCLOM_16Y_HACK | 664 | #ifdef CYCLOM_16Y_HACK |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 268e17f9ec3f..07ac14d949ce 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -646,8 +646,6 @@ static void sx_receive(struct specialix_board *bp) | |||
646 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); | 646 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); |
647 | port->hits[count > 8 ? 9 : count]++; | 647 | port->hits[count > 8 ? 9 : count]++; |
648 | 648 | ||
649 | tty_buffer_request_room(tty, count); | ||
650 | |||
651 | while (count--) | 649 | while (count--) |
652 | tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); | 650 | tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); |
653 | tty_flip_buffer_push(tty); | 651 | tty_flip_buffer_push(tty); |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 4846b73ef28d..0658fc548222 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) | |||
2031 | if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) | 2031 | if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) |
2032 | return 0; | 2032 | return 0; |
2033 | 2033 | ||
2034 | if (!tty || !info->xmit_buf) | 2034 | if (!info->xmit_buf) |
2035 | return 0; | 2035 | return 0; |
2036 | 2036 | ||
2037 | spin_lock_irqsave(&info->irq_spinlock, flags); | 2037 | spin_lock_irqsave(&info->irq_spinlock, flags); |
@@ -2121,7 +2121,7 @@ static int mgsl_write(struct tty_struct * tty, | |||
2121 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) | 2121 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) |
2122 | goto cleanup; | 2122 | goto cleanup; |
2123 | 2123 | ||
2124 | if (!tty || !info->xmit_buf) | 2124 | if (!info->xmit_buf) |
2125 | goto cleanup; | 2125 | goto cleanup; |
2126 | 2126 | ||
2127 | if ( info->params.mode == MGSL_MODE_HDLC || | 2127 | if ( info->params.mode == MGSL_MODE_HDLC || |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 8678f0c8699d..4561ce2fba6d 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); | |||
468 | static unsigned int tbuf_bytes(struct slgt_info *info); | 468 | static unsigned int tbuf_bytes(struct slgt_info *info); |
469 | static void reset_tbufs(struct slgt_info *info); | 469 | static void reset_tbufs(struct slgt_info *info); |
470 | static void tdma_reset(struct slgt_info *info); | 470 | static void tdma_reset(struct slgt_info *info); |
471 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); | 471 | static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count); |
472 | 472 | ||
473 | static void get_signals(struct slgt_info *info); | 473 | static void get_signals(struct slgt_info *info); |
474 | static void set_signals(struct slgt_info *info); | 474 | static void set_signals(struct slgt_info *info); |
@@ -813,59 +813,32 @@ static int write(struct tty_struct *tty, | |||
813 | int ret = 0; | 813 | int ret = 0; |
814 | struct slgt_info *info = tty->driver_data; | 814 | struct slgt_info *info = tty->driver_data; |
815 | unsigned long flags; | 815 | unsigned long flags; |
816 | unsigned int bufs_needed; | ||
817 | 816 | ||
818 | if (sanity_check(info, tty->name, "write")) | 817 | if (sanity_check(info, tty->name, "write")) |
819 | goto cleanup; | 818 | return -EIO; |
819 | |||
820 | DBGINFO(("%s write count=%d\n", info->device_name, count)); | 820 | DBGINFO(("%s write count=%d\n", info->device_name, count)); |
821 | 821 | ||
822 | if (!info->tx_buf) | 822 | if (!info->tx_buf || (count > info->max_frame_size)) |
823 | goto cleanup; | 823 | return -EIO; |
824 | 824 | ||
825 | if (count > info->max_frame_size) { | 825 | if (!count || tty->stopped || tty->hw_stopped) |
826 | ret = -EIO; | 826 | return 0; |
827 | goto cleanup; | ||
828 | } | ||
829 | 827 | ||
830 | if (!count) | 828 | spin_lock_irqsave(&info->lock, flags); |
831 | goto cleanup; | ||
832 | 829 | ||
833 | if (!info->tx_active && info->tx_count) { | 830 | if (info->tx_count) { |
834 | /* send accumulated data from send_char() */ | 831 | /* send accumulated data from send_char() */ |
835 | tx_load(info, info->tx_buf, info->tx_count); | 832 | if (!tx_load(info, info->tx_buf, info->tx_count)) |
836 | goto start; | 833 | goto cleanup; |
834 | info->tx_count = 0; | ||
837 | } | 835 | } |
838 | bufs_needed = (count/DMABUFSIZE); | ||
839 | if (count % DMABUFSIZE) | ||
840 | ++bufs_needed; | ||
841 | if (bufs_needed > free_tbuf_count(info)) | ||
842 | goto cleanup; | ||
843 | 836 | ||
844 | ret = info->tx_count = count; | 837 | if (tx_load(info, buf, count)) |
845 | tx_load(info, buf, count); | 838 | ret = count; |
846 | goto start; | ||
847 | |||
848 | start: | ||
849 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { | ||
850 | spin_lock_irqsave(&info->lock,flags); | ||
851 | if (!info->tx_active) | ||
852 | tx_start(info); | ||
853 | else if (!(rd_reg32(info, TDCSR) & BIT0)) { | ||
854 | /* transmit still active but transmit DMA stopped */ | ||
855 | unsigned int i = info->tbuf_current; | ||
856 | if (!i) | ||
857 | i = info->tbuf_count; | ||
858 | i--; | ||
859 | /* if DMA buf unsent must try later after tx idle */ | ||
860 | if (desc_count(info->tbufs[i])) | ||
861 | ret = 0; | ||
862 | } | ||
863 | if (ret > 0) | ||
864 | update_tx_timer(info); | ||
865 | spin_unlock_irqrestore(&info->lock,flags); | ||
866 | } | ||
867 | 839 | ||
868 | cleanup: | 840 | cleanup: |
841 | spin_unlock_irqrestore(&info->lock, flags); | ||
869 | DBGINFO(("%s write rc=%d\n", info->device_name, ret)); | 842 | DBGINFO(("%s write rc=%d\n", info->device_name, ret)); |
870 | return ret; | 843 | return ret; |
871 | } | 844 | } |
@@ -882,7 +855,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch) | |||
882 | if (!info->tx_buf) | 855 | if (!info->tx_buf) |
883 | return 0; | 856 | return 0; |
884 | spin_lock_irqsave(&info->lock,flags); | 857 | spin_lock_irqsave(&info->lock,flags); |
885 | if (!info->tx_active && (info->tx_count < info->max_frame_size)) { | 858 | if (info->tx_count < info->max_frame_size) { |
886 | info->tx_buf[info->tx_count++] = ch; | 859 | info->tx_buf[info->tx_count++] = ch; |
887 | ret = 1; | 860 | ret = 1; |
888 | } | 861 | } |
@@ -981,10 +954,8 @@ static void flush_chars(struct tty_struct *tty) | |||
981 | DBGINFO(("%s flush_chars start transmit\n", info->device_name)); | 954 | DBGINFO(("%s flush_chars start transmit\n", info->device_name)); |
982 | 955 | ||
983 | spin_lock_irqsave(&info->lock,flags); | 956 | spin_lock_irqsave(&info->lock,flags); |
984 | if (!info->tx_active && info->tx_count) { | 957 | if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) |
985 | tx_load(info, info->tx_buf,info->tx_count); | 958 | info->tx_count = 0; |
986 | tx_start(info); | ||
987 | } | ||
988 | spin_unlock_irqrestore(&info->lock,flags); | 959 | spin_unlock_irqrestore(&info->lock,flags); |
989 | } | 960 | } |
990 | 961 | ||
@@ -997,10 +968,9 @@ static void flush_buffer(struct tty_struct *tty) | |||
997 | return; | 968 | return; |
998 | DBGINFO(("%s flush_buffer\n", info->device_name)); | 969 | DBGINFO(("%s flush_buffer\n", info->device_name)); |
999 | 970 | ||
1000 | spin_lock_irqsave(&info->lock,flags); | 971 | spin_lock_irqsave(&info->lock, flags); |
1001 | if (!info->tx_active) | 972 | info->tx_count = 0; |
1002 | info->tx_count = 0; | 973 | spin_unlock_irqrestore(&info->lock, flags); |
1003 | spin_unlock_irqrestore(&info->lock,flags); | ||
1004 | 974 | ||
1005 | tty_wakeup(tty); | 975 | tty_wakeup(tty); |
1006 | } | 976 | } |
@@ -1033,12 +1003,10 @@ static void tx_release(struct tty_struct *tty) | |||
1033 | if (sanity_check(info, tty->name, "tx_release")) | 1003 | if (sanity_check(info, tty->name, "tx_release")) |
1034 | return; | 1004 | return; |
1035 | DBGINFO(("%s tx_release\n", info->device_name)); | 1005 | DBGINFO(("%s tx_release\n", info->device_name)); |
1036 | spin_lock_irqsave(&info->lock,flags); | 1006 | spin_lock_irqsave(&info->lock, flags); |
1037 | if (!info->tx_active && info->tx_count) { | 1007 | if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) |
1038 | tx_load(info, info->tx_buf, info->tx_count); | 1008 | info->tx_count = 0; |
1039 | tx_start(info); | 1009 | spin_unlock_irqrestore(&info->lock, flags); |
1040 | } | ||
1041 | spin_unlock_irqrestore(&info->lock,flags); | ||
1042 | } | 1010 | } |
1043 | 1011 | ||
1044 | /* | 1012 | /* |
@@ -1506,27 +1474,25 @@ static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, | |||
1506 | 1474 | ||
1507 | DBGINFO(("%s hdlc_xmit\n", dev->name)); | 1475 | DBGINFO(("%s hdlc_xmit\n", dev->name)); |
1508 | 1476 | ||
1477 | if (!skb->len) | ||
1478 | return NETDEV_TX_OK; | ||
1479 | |||
1509 | /* stop sending until this frame completes */ | 1480 | /* stop sending until this frame completes */ |
1510 | netif_stop_queue(dev); | 1481 | netif_stop_queue(dev); |
1511 | 1482 | ||
1512 | /* copy data to device buffers */ | ||
1513 | info->tx_count = skb->len; | ||
1514 | tx_load(info, skb->data, skb->len); | ||
1515 | |||
1516 | /* update network statistics */ | 1483 | /* update network statistics */ |
1517 | dev->stats.tx_packets++; | 1484 | dev->stats.tx_packets++; |
1518 | dev->stats.tx_bytes += skb->len; | 1485 | dev->stats.tx_bytes += skb->len; |
1519 | 1486 | ||
1520 | /* done with socket buffer, so free it */ | ||
1521 | dev_kfree_skb(skb); | ||
1522 | |||
1523 | /* save start time for transmit timeout detection */ | 1487 | /* save start time for transmit timeout detection */ |
1524 | dev->trans_start = jiffies; | 1488 | dev->trans_start = jiffies; |
1525 | 1489 | ||
1526 | spin_lock_irqsave(&info->lock,flags); | 1490 | spin_lock_irqsave(&info->lock, flags); |
1527 | tx_start(info); | 1491 | tx_load(info, skb->data, skb->len); |
1528 | update_tx_timer(info); | 1492 | spin_unlock_irqrestore(&info->lock, flags); |
1529 | spin_unlock_irqrestore(&info->lock,flags); | 1493 | |
1494 | /* done with socket buffer, so free it */ | ||
1495 | dev_kfree_skb(skb); | ||
1530 | 1496 | ||
1531 | return NETDEV_TX_OK; | 1497 | return NETDEV_TX_OK; |
1532 | } | 1498 | } |
@@ -2180,7 +2146,7 @@ static void isr_serial(struct slgt_info *info) | |||
2180 | 2146 | ||
2181 | if (info->params.mode == MGSL_MODE_ASYNC) { | 2147 | if (info->params.mode == MGSL_MODE_ASYNC) { |
2182 | if (status & IRQ_TXIDLE) { | 2148 | if (status & IRQ_TXIDLE) { |
2183 | if (info->tx_count) | 2149 | if (info->tx_active) |
2184 | isr_txeom(info, status); | 2150 | isr_txeom(info, status); |
2185 | } | 2151 | } |
2186 | if (info->rx_pio && (status & IRQ_RXDATA)) | 2152 | if (info->rx_pio && (status & IRQ_RXDATA)) |
@@ -2276,13 +2242,42 @@ static void isr_tdma(struct slgt_info *info) | |||
2276 | } | 2242 | } |
2277 | } | 2243 | } |
2278 | 2244 | ||
2245 | /* | ||
2246 | * return true if there are unsent tx DMA buffers, otherwise false | ||
2247 | * | ||
2248 | * if there are unsent buffers then info->tbuf_start | ||
2249 | * is set to index of first unsent buffer | ||
2250 | */ | ||
2251 | static bool unsent_tbufs(struct slgt_info *info) | ||
2252 | { | ||
2253 | unsigned int i = info->tbuf_current; | ||
2254 | bool rc = false; | ||
2255 | |||
2256 | /* | ||
2257 | * search backwards from last loaded buffer (precedes tbuf_current) | ||
2258 | * for first unsent buffer (desc_count > 0) | ||
2259 | */ | ||
2260 | |||
2261 | do { | ||
2262 | if (i) | ||
2263 | i--; | ||
2264 | else | ||
2265 | i = info->tbuf_count - 1; | ||
2266 | if (!desc_count(info->tbufs[i])) | ||
2267 | break; | ||
2268 | info->tbuf_start = i; | ||
2269 | rc = true; | ||
2270 | } while (i != info->tbuf_current); | ||
2271 | |||
2272 | return rc; | ||
2273 | } | ||
2274 | |||
2279 | static void isr_txeom(struct slgt_info *info, unsigned short status) | 2275 | static void isr_txeom(struct slgt_info *info, unsigned short status) |
2280 | { | 2276 | { |
2281 | DBGISR(("%s txeom status=%04x\n", info->device_name, status)); | 2277 | DBGISR(("%s txeom status=%04x\n", info->device_name, status)); |
2282 | 2278 | ||
2283 | slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); | 2279 | slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); |
2284 | tdma_reset(info); | 2280 | tdma_reset(info); |
2285 | reset_tbufs(info); | ||
2286 | if (status & IRQ_TXUNDER) { | 2281 | if (status & IRQ_TXUNDER) { |
2287 | unsigned short val = rd_reg16(info, TCR); | 2282 | unsigned short val = rd_reg16(info, TCR); |
2288 | wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ | 2283 | wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ |
@@ -2297,8 +2292,12 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) | |||
2297 | info->icount.txok++; | 2292 | info->icount.txok++; |
2298 | } | 2293 | } |
2299 | 2294 | ||
2295 | if (unsent_tbufs(info)) { | ||
2296 | tx_start(info); | ||
2297 | update_tx_timer(info); | ||
2298 | return; | ||
2299 | } | ||
2300 | info->tx_active = false; | 2300 | info->tx_active = false; |
2301 | info->tx_count = 0; | ||
2302 | 2301 | ||
2303 | del_timer(&info->tx_timer); | 2302 | del_timer(&info->tx_timer); |
2304 | 2303 | ||
@@ -3949,7 +3948,7 @@ static void tx_start(struct slgt_info *info) | |||
3949 | info->tx_enabled = true; | 3948 | info->tx_enabled = true; |
3950 | } | 3949 | } |
3951 | 3950 | ||
3952 | if (info->tx_count) { | 3951 | if (desc_count(info->tbufs[info->tbuf_start])) { |
3953 | info->drop_rts_on_tx_done = false; | 3952 | info->drop_rts_on_tx_done = false; |
3954 | 3953 | ||
3955 | if (info->params.mode != MGSL_MODE_ASYNC) { | 3954 | if (info->params.mode != MGSL_MODE_ASYNC) { |
@@ -4772,25 +4771,36 @@ static unsigned int tbuf_bytes(struct slgt_info *info) | |||
4772 | } | 4771 | } |
4773 | 4772 | ||
4774 | /* | 4773 | /* |
4775 | * load transmit DMA buffer(s) with data | 4774 | * load data into transmit DMA buffer ring and start transmitter if needed |
4775 | * return true if data accepted, otherwise false (buffers full) | ||
4776 | */ | 4776 | */ |
4777 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | 4777 | static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size) |
4778 | { | 4778 | { |
4779 | unsigned short count; | 4779 | unsigned short count; |
4780 | unsigned int i; | 4780 | unsigned int i; |
4781 | struct slgt_desc *d; | 4781 | struct slgt_desc *d; |
4782 | 4782 | ||
4783 | if (size == 0) | 4783 | /* check required buffer space */ |
4784 | return; | 4784 | if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info)) |
4785 | return false; | ||
4785 | 4786 | ||
4786 | DBGDATA(info, buf, size, "tx"); | 4787 | DBGDATA(info, buf, size, "tx"); |
4787 | 4788 | ||
4789 | /* | ||
4790 | * copy data to one or more DMA buffers in circular ring | ||
4791 | * tbuf_start = first buffer for this data | ||
4792 | * tbuf_current = next free buffer | ||
4793 | * | ||
4794 | * Copy all data before making data visible to DMA controller by | ||
4795 | * setting descriptor count of the first buffer. | ||
4796 | * This prevents an active DMA controller from reading the first DMA | ||
4797 | * buffers of a frame and stopping before the final buffers are filled. | ||
4798 | */ | ||
4799 | |||
4788 | info->tbuf_start = i = info->tbuf_current; | 4800 | info->tbuf_start = i = info->tbuf_current; |
4789 | 4801 | ||
4790 | while (size) { | 4802 | while (size) { |
4791 | d = &info->tbufs[i]; | 4803 | d = &info->tbufs[i]; |
4792 | if (++i == info->tbuf_count) | ||
4793 | i = 0; | ||
4794 | 4804 | ||
4795 | count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); | 4805 | count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); |
4796 | memcpy(d->buf, buf, count); | 4806 | memcpy(d->buf, buf, count); |
@@ -4808,11 +4818,27 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | |||
4808 | else | 4818 | else |
4809 | set_desc_eof(*d, 0); | 4819 | set_desc_eof(*d, 0); |
4810 | 4820 | ||
4811 | set_desc_count(*d, count); | 4821 | /* set descriptor count for all but first buffer */ |
4822 | if (i != info->tbuf_start) | ||
4823 | set_desc_count(*d, count); | ||
4812 | d->buf_count = count; | 4824 | d->buf_count = count; |
4825 | |||
4826 | if (++i == info->tbuf_count) | ||
4827 | i = 0; | ||
4813 | } | 4828 | } |
4814 | 4829 | ||
4815 | info->tbuf_current = i; | 4830 | info->tbuf_current = i; |
4831 | |||
4832 | /* set first buffer count to make new data visible to DMA controller */ | ||
4833 | d = &info->tbufs[info->tbuf_start]; | ||
4834 | set_desc_count(*d, d->buf_count); | ||
4835 | |||
4836 | /* start transmitter if needed and update transmit timeout */ | ||
4837 | if (!info->tx_active) | ||
4838 | tx_start(info); | ||
4839 | update_tx_timer(info); | ||
4840 | |||
4841 | return true; | ||
4816 | } | 4842 | } |
4817 | 4843 | ||
4818 | static int register_test(struct slgt_info *info) | 4844 | static int register_test(struct slgt_info *info) |
@@ -4934,9 +4960,7 @@ static int loopback_test(struct slgt_info *info) | |||
4934 | spin_lock_irqsave(&info->lock,flags); | 4960 | spin_lock_irqsave(&info->lock,flags); |
4935 | async_mode(info); | 4961 | async_mode(info); |
4936 | rx_start(info); | 4962 | rx_start(info); |
4937 | info->tx_count = count; | ||
4938 | tx_load(info, buf, count); | 4963 | tx_load(info, buf, count); |
4939 | tx_start(info); | ||
4940 | spin_unlock_irqrestore(&info->lock, flags); | 4964 | spin_unlock_irqrestore(&info->lock, flags); |
4941 | 4965 | ||
4942 | /* wait for receive complete */ | 4966 | /* wait for receive complete */ |
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c index 66fa4e10d76b..f27c4d6d956e 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/char/tty_buffer.c | |||
@@ -247,7 +247,8 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, | |||
247 | { | 247 | { |
248 | int copied = 0; | 248 | int copied = 0; |
249 | do { | 249 | do { |
250 | int space = tty_buffer_request_room(tty, size - copied); | 250 | int goal = min(size - copied, TTY_BUFFER_PAGE); |
251 | int space = tty_buffer_request_room(tty, goal); | ||
251 | struct tty_buffer *tb = tty->buf.tail; | 252 | struct tty_buffer *tb = tty->buf.tail; |
252 | /* If there is no space then tb may be NULL */ | 253 | /* If there is no space then tb may be NULL */ |
253 | if (unlikely(space == 0)) | 254 | if (unlikely(space == 0)) |
@@ -283,7 +284,8 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, | |||
283 | { | 284 | { |
284 | int copied = 0; | 285 | int copied = 0; |
285 | do { | 286 | do { |
286 | int space = tty_buffer_request_room(tty, size - copied); | 287 | int goal = min(size - copied, TTY_BUFFER_PAGE); |
288 | int space = tty_buffer_request_room(tty, goal); | ||
287 | struct tty_buffer *tb = tty->buf.tail; | 289 | struct tty_buffer *tb = tty->buf.tail; |
288 | /* If there is no space then tb may be NULL */ | 290 | /* If there is no space then tb may be NULL */ |
289 | if (unlikely(space == 0)) | 291 | if (unlikely(space == 0)) |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 3f653f7d849f..500e740ec5e4 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -706,12 +706,13 @@ static void tty_reset_termios(struct tty_struct *tty) | |||
706 | /** | 706 | /** |
707 | * tty_ldisc_reinit - reinitialise the tty ldisc | 707 | * tty_ldisc_reinit - reinitialise the tty ldisc |
708 | * @tty: tty to reinit | 708 | * @tty: tty to reinit |
709 | * @ldisc: line discipline to reinitialize | ||
709 | * | 710 | * |
710 | * Switch the tty back to N_TTY line discipline and leave the | 711 | * Switch the tty to a line discipline and leave the ldisc |
711 | * ldisc state closed | 712 | * state closed |
712 | */ | 713 | */ |
713 | 714 | ||
714 | static void tty_ldisc_reinit(struct tty_struct *tty) | 715 | static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc) |
715 | { | 716 | { |
716 | struct tty_ldisc *ld; | 717 | struct tty_ldisc *ld; |
717 | 718 | ||
@@ -721,10 +722,10 @@ static void tty_ldisc_reinit(struct tty_struct *tty) | |||
721 | /* | 722 | /* |
722 | * Switch the line discipline back | 723 | * Switch the line discipline back |
723 | */ | 724 | */ |
724 | ld = tty_ldisc_get(N_TTY); | 725 | ld = tty_ldisc_get(ldisc); |
725 | BUG_ON(IS_ERR(ld)); | 726 | BUG_ON(IS_ERR(ld)); |
726 | tty_ldisc_assign(tty, ld); | 727 | tty_ldisc_assign(tty, ld); |
727 | tty_set_termios_ldisc(tty, N_TTY); | 728 | tty_set_termios_ldisc(tty, ldisc); |
728 | } | 729 | } |
729 | 730 | ||
730 | /** | 731 | /** |
@@ -745,6 +746,8 @@ static void tty_ldisc_reinit(struct tty_struct *tty) | |||
745 | void tty_ldisc_hangup(struct tty_struct *tty) | 746 | void tty_ldisc_hangup(struct tty_struct *tty) |
746 | { | 747 | { |
747 | struct tty_ldisc *ld; | 748 | struct tty_ldisc *ld; |
749 | int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; | ||
750 | int err = 0; | ||
748 | 751 | ||
749 | /* | 752 | /* |
750 | * FIXME! What are the locking issues here? This may me overdoing | 753 | * FIXME! What are the locking issues here? This may me overdoing |
@@ -772,25 +775,32 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
772 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | 775 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
773 | /* | 776 | /* |
774 | * Shutdown the current line discipline, and reset it to | 777 | * Shutdown the current line discipline, and reset it to |
775 | * N_TTY. | 778 | * N_TTY if need be. |
779 | * | ||
780 | * Avoid racing set_ldisc or tty_ldisc_release | ||
776 | */ | 781 | */ |
777 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | 782 | mutex_lock(&tty->ldisc_mutex); |
778 | /* Avoid racing set_ldisc or tty_ldisc_release */ | 783 | tty_ldisc_halt(tty); |
779 | mutex_lock(&tty->ldisc_mutex); | 784 | /* At this point we have a closed ldisc and we want to |
780 | tty_ldisc_halt(tty); | 785 | reopen it. We could defer this to the next open but |
781 | if (tty->ldisc) { /* Not yet closed */ | 786 | it means auditing a lot of other paths so this is |
782 | /* Switch back to N_TTY */ | 787 | a FIXME */ |
783 | tty_ldisc_reinit(tty); | 788 | if (tty->ldisc) { /* Not yet closed */ |
784 | /* At this point we have a closed ldisc and we want to | 789 | if (reset == 0) { |
785 | reopen it. We could defer this to the next open but | 790 | tty_ldisc_reinit(tty, tty->termios->c_line); |
786 | it means auditing a lot of other paths so this is | 791 | err = tty_ldisc_open(tty, tty->ldisc); |
787 | a FIXME */ | 792 | } |
793 | /* If the re-open fails or we reset then go to N_TTY. The | ||
794 | N_TTY open cannot fail */ | ||
795 | if (reset || err) { | ||
796 | tty_ldisc_reinit(tty, N_TTY); | ||
788 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | 797 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); |
789 | tty_ldisc_enable(tty); | ||
790 | } | 798 | } |
791 | mutex_unlock(&tty->ldisc_mutex); | 799 | tty_ldisc_enable(tty); |
792 | tty_reset_termios(tty); | ||
793 | } | 800 | } |
801 | mutex_unlock(&tty->ldisc_mutex); | ||
802 | if (reset) | ||
803 | tty_reset_termios(tty); | ||
794 | } | 804 | } |
795 | 805 | ||
796 | /** | 806 | /** |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 6aa10284104a..87778dcf8727 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -888,7 +888,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
888 | ret = -EFAULT; | 888 | ret = -EFAULT; |
889 | goto out; | 889 | goto out; |
890 | } | 890 | } |
891 | if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { | 891 | if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS && tmp.mode != VT_PROCESS_AUTO) { |
892 | ret = -EINVAL; | 892 | ret = -EINVAL; |
893 | goto out; | 893 | goto out; |
894 | } | 894 | } |
@@ -1622,7 +1622,7 @@ static void complete_change_console(struct vc_data *vc) | |||
1622 | * telling it that it has acquired. Also check if it has died and | 1622 | * telling it that it has acquired. Also check if it has died and |
1623 | * clean up (similar to logic employed in change_console()) | 1623 | * clean up (similar to logic employed in change_console()) |
1624 | */ | 1624 | */ |
1625 | if (vc->vt_mode.mode == VT_PROCESS) { | 1625 | if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) { |
1626 | /* | 1626 | /* |
1627 | * Send the signal as privileged - kill_pid() will | 1627 | * Send the signal as privileged - kill_pid() will |
1628 | * tell us if the process has gone or something else | 1628 | * tell us if the process has gone or something else |
@@ -1682,7 +1682,7 @@ void change_console(struct vc_data *new_vc) | |||
1682 | * vt to auto control. | 1682 | * vt to auto control. |
1683 | */ | 1683 | */ |
1684 | vc = vc_cons[fg_console].d; | 1684 | vc = vc_cons[fg_console].d; |
1685 | if (vc->vt_mode.mode == VT_PROCESS) { | 1685 | if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) { |
1686 | /* | 1686 | /* |
1687 | * Send the signal as privileged - kill_pid() will | 1687 | * Send the signal as privileged - kill_pid() will |
1688 | * tell us if the process has gone or something else | 1688 | * tell us if the process has gone or something else |
@@ -1693,27 +1693,28 @@ void change_console(struct vc_data *new_vc) | |||
1693 | */ | 1693 | */ |
1694 | vc->vt_newvt = new_vc->vc_num; | 1694 | vc->vt_newvt = new_vc->vc_num; |
1695 | if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { | 1695 | if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { |
1696 | if(vc->vt_mode.mode == VT_PROCESS) | ||
1697 | /* | ||
1698 | * It worked. Mark the vt to switch to and | ||
1699 | * return. The process needs to send us a | ||
1700 | * VT_RELDISP ioctl to complete the switch. | ||
1701 | */ | ||
1702 | return; | ||
1703 | } else { | ||
1696 | /* | 1704 | /* |
1697 | * It worked. Mark the vt to switch to and | 1705 | * The controlling process has died, so we revert back to |
1698 | * return. The process needs to send us a | 1706 | * normal operation. In this case, we'll also change back |
1699 | * VT_RELDISP ioctl to complete the switch. | 1707 | * to KD_TEXT mode. I'm not sure if this is strictly correct |
1708 | * but it saves the agony when the X server dies and the screen | ||
1709 | * remains blanked due to KD_GRAPHICS! It would be nice to do | ||
1710 | * this outside of VT_PROCESS but there is no single process | ||
1711 | * to account for and tracking tty count may be undesirable. | ||
1700 | */ | 1712 | */ |
1701 | return; | 1713 | reset_vc(vc); |
1702 | } | 1714 | } |
1703 | 1715 | ||
1704 | /* | 1716 | /* |
1705 | * The controlling process has died, so we revert back to | 1717 | * Fall through to normal (VT_AUTO and VT_PROCESS_AUTO) handling of the switch... |
1706 | * normal operation. In this case, we'll also change back | ||
1707 | * to KD_TEXT mode. I'm not sure if this is strictly correct | ||
1708 | * but it saves the agony when the X server dies and the screen | ||
1709 | * remains blanked due to KD_GRAPHICS! It would be nice to do | ||
1710 | * this outside of VT_PROCESS but there is no single process | ||
1711 | * to account for and tracking tty count may be undesirable. | ||
1712 | */ | ||
1713 | reset_vc(vc); | ||
1714 | |||
1715 | /* | ||
1716 | * Fall through to normal (VT_AUTO) handling of the switch... | ||
1717 | */ | 1718 | */ |
1718 | } | 1719 | } |
1719 | 1720 | ||