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 | |
| 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.
...
36 files changed, 978 insertions, 652 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 | ||
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index f53755533e7e..3fab78ba8952 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/gfp.h> | 37 | #include <linux/gfp.h> |
| 38 | #include <linux/tty.h> | 38 | #include <linux/tty.h> |
| 39 | #include <linux/tty_flip.h> | 39 | #include <linux/tty_flip.h> |
| 40 | #include <linux/kfifo.h> | ||
| 40 | 41 | ||
| 41 | #include <linux/mmc/core.h> | 42 | #include <linux/mmc/core.h> |
| 42 | #include <linux/mmc/card.h> | 43 | #include <linux/mmc/card.h> |
| @@ -47,19 +48,9 @@ | |||
| 47 | #define UART_NR 8 /* Number of UARTs this driver can handle */ | 48 | #define UART_NR 8 /* Number of UARTs this driver can handle */ |
| 48 | 49 | ||
| 49 | 50 | ||
| 50 | #define UART_XMIT_SIZE PAGE_SIZE | 51 | #define FIFO_SIZE PAGE_SIZE |
| 51 | #define WAKEUP_CHARS 256 | 52 | #define WAKEUP_CHARS 256 |
| 52 | 53 | ||
| 53 | #define circ_empty(circ) ((circ)->head == (circ)->tail) | ||
| 54 | #define circ_clear(circ) ((circ)->head = (circ)->tail = 0) | ||
| 55 | |||
| 56 | #define circ_chars_pending(circ) \ | ||
| 57 | (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | ||
| 58 | |||
| 59 | #define circ_chars_free(circ) \ | ||
| 60 | (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | ||
| 61 | |||
| 62 | |||
| 63 | struct uart_icount { | 54 | struct uart_icount { |
| 64 | __u32 cts; | 55 | __u32 cts; |
| 65 | __u32 dsr; | 56 | __u32 dsr; |
| @@ -82,7 +73,7 @@ struct sdio_uart_port { | |||
| 82 | struct mutex func_lock; | 73 | struct mutex func_lock; |
| 83 | struct task_struct *in_sdio_uart_irq; | 74 | struct task_struct *in_sdio_uart_irq; |
| 84 | unsigned int regs_offset; | 75 | unsigned int regs_offset; |
| 85 | struct circ_buf xmit; | 76 | struct kfifo xmit_fifo; |
| 86 | spinlock_t write_lock; | 77 | spinlock_t write_lock; |
| 87 | struct uart_icount icount; | 78 | struct uart_icount icount; |
| 88 | unsigned int uartclk; | 79 | unsigned int uartclk; |
| @@ -105,6 +96,8 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) | |||
| 105 | kref_init(&port->kref); | 96 | kref_init(&port->kref); |
| 106 | mutex_init(&port->func_lock); | 97 | mutex_init(&port->func_lock); |
| 107 | spin_lock_init(&port->write_lock); | 98 | spin_lock_init(&port->write_lock); |
| 99 | if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL)) | ||
| 100 | return -ENOMEM; | ||
| 108 | 101 | ||
| 109 | spin_lock(&sdio_uart_table_lock); | 102 | spin_lock(&sdio_uart_table_lock); |
| 110 | for (index = 0; index < UART_NR; index++) { | 103 | for (index = 0; index < UART_NR; index++) { |
| @@ -140,6 +133,7 @@ static void sdio_uart_port_destroy(struct kref *kref) | |||
| 140 | { | 133 | { |
| 141 | struct sdio_uart_port *port = | 134 | struct sdio_uart_port *port = |
| 142 | container_of(kref, struct sdio_uart_port, kref); | 135 | container_of(kref, struct sdio_uart_port, kref); |
| 136 | kfifo_free(&port->xmit_fifo); | ||
| 143 | kfree(port); | 137 | kfree(port); |
| 144 | } | 138 | } |
| 145 | 139 | ||
| @@ -456,9 +450,11 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, | |||
| 456 | 450 | ||
| 457 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 451 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) |
| 458 | { | 452 | { |
| 459 | struct circ_buf *xmit = &port->xmit; | 453 | struct kfifo *xmit = &port->xmit_fifo; |
| 460 | int count; | 454 | int count; |
| 461 | struct tty_struct *tty; | 455 | struct tty_struct *tty; |
| 456 | u8 iobuf[16]; | ||
| 457 | int len; | ||
| 462 | 458 | ||
| 463 | if (port->x_char) { | 459 | if (port->x_char) { |
| 464 | sdio_out(port, UART_TX, port->x_char); | 460 | sdio_out(port, UART_TX, port->x_char); |
| @@ -469,27 +465,25 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
| 469 | 465 | ||
| 470 | tty = tty_port_tty_get(&port->port); | 466 | tty = tty_port_tty_get(&port->port); |
| 471 | 467 | ||
| 472 | if (tty == NULL || circ_empty(xmit) || | 468 | if (tty == NULL || !kfifo_len(xmit) || |
| 473 | tty->stopped || tty->hw_stopped) { | 469 | tty->stopped || tty->hw_stopped) { |
| 474 | sdio_uart_stop_tx(port); | 470 | sdio_uart_stop_tx(port); |
| 475 | tty_kref_put(tty); | 471 | tty_kref_put(tty); |
| 476 | return; | 472 | return; |
| 477 | } | 473 | } |
| 478 | 474 | ||
| 479 | count = 16; | 475 | len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock); |
| 480 | do { | 476 | for (count = 0; count < len; count++) { |
| 481 | sdio_out(port, UART_TX, xmit->buf[xmit->tail]); | 477 | sdio_out(port, UART_TX, iobuf[count]); |
| 482 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
| 483 | port->icount.tx++; | 478 | port->icount.tx++; |
| 484 | if (circ_empty(xmit)) | 479 | } |
| 485 | break; | ||
| 486 | } while (--count > 0); | ||
| 487 | 480 | ||
| 488 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | 481 | len = kfifo_len(xmit); |
| 482 | if (len < WAKEUP_CHARS) { | ||
| 489 | tty_wakeup(tty); | 483 | tty_wakeup(tty); |
| 490 | 484 | if (len == 0) | |
| 491 | if (circ_empty(xmit)) | 485 | sdio_uart_stop_tx(port); |
| 492 | sdio_uart_stop_tx(port); | 486 | } |
| 493 | tty_kref_put(tty); | 487 | tty_kref_put(tty); |
| 494 | } | 488 | } |
| 495 | 489 | ||
| @@ -632,7 +626,6 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | |||
| 632 | { | 626 | { |
| 633 | struct sdio_uart_port *port = | 627 | struct sdio_uart_port *port = |
| 634 | container_of(tport, struct sdio_uart_port, port); | 628 | container_of(tport, struct sdio_uart_port, port); |
| 635 | unsigned long page; | ||
| 636 | int ret; | 629 | int ret; |
| 637 | 630 | ||
| 638 | /* | 631 | /* |
| @@ -641,22 +634,17 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | |||
| 641 | */ | 634 | */ |
| 642 | set_bit(TTY_IO_ERROR, &tty->flags); | 635 | set_bit(TTY_IO_ERROR, &tty->flags); |
| 643 | 636 | ||
| 644 | /* Initialise and allocate the transmit buffer. */ | 637 | kfifo_reset(&port->xmit_fifo); |
| 645 | page = __get_free_page(GFP_KERNEL); | ||
| 646 | if (!page) | ||
| 647 | return -ENOMEM; | ||
| 648 | port->xmit.buf = (unsigned char *)page; | ||
| 649 | circ_clear(&port->xmit); | ||
| 650 | 638 | ||
| 651 | ret = sdio_uart_claim_func(port); | 639 | ret = sdio_uart_claim_func(port); |
| 652 | if (ret) | 640 | if (ret) |
| 653 | goto err1; | 641 | return ret; |
| 654 | ret = sdio_enable_func(port->func); | 642 | ret = sdio_enable_func(port->func); |
| 655 | if (ret) | 643 | if (ret) |
| 656 | goto err2; | 644 | goto err1; |
| 657 | ret = sdio_claim_irq(port->func, sdio_uart_irq); | 645 | ret = sdio_claim_irq(port->func, sdio_uart_irq); |
| 658 | if (ret) | 646 | if (ret) |
| 659 | goto err3; | 647 | goto err2; |
| 660 | 648 | ||
| 661 | /* | 649 | /* |
| 662 | * Clear the FIFO buffers and disable them. | 650 | * Clear the FIFO buffers and disable them. |
| @@ -700,12 +688,10 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | |||
| 700 | sdio_uart_release_func(port); | 688 | sdio_uart_release_func(port); |
| 701 | return 0; | 689 | return 0; |
| 702 | 690 | ||
| 703 | err3: | ||
| 704 | sdio_disable_func(port->func); | ||
| 705 | err2: | 691 | err2: |
| 706 | sdio_uart_release_func(port); | 692 | sdio_disable_func(port->func); |
| 707 | err1: | 693 | err1: |
| 708 | free_page((unsigned long)port->xmit.buf); | 694 | sdio_uart_release_func(port); |
| 709 | return ret; | 695 | return ret; |
| 710 | } | 696 | } |
| 711 | 697 | ||
| @@ -727,7 +713,7 @@ static void sdio_uart_shutdown(struct tty_port *tport) | |||
| 727 | 713 | ||
| 728 | ret = sdio_uart_claim_func(port); | 714 | ret = sdio_uart_claim_func(port); |
| 729 | if (ret) | 715 | if (ret) |
| 730 | goto skip; | 716 | return; |
| 731 | 717 | ||
| 732 | sdio_uart_stop_rx(port); | 718 | sdio_uart_stop_rx(port); |
| 733 | 719 | ||
| @@ -749,10 +735,6 @@ static void sdio_uart_shutdown(struct tty_port *tport) | |||
| 749 | sdio_disable_func(port->func); | 735 | sdio_disable_func(port->func); |
| 750 | 736 | ||
| 751 | sdio_uart_release_func(port); | 737 | sdio_uart_release_func(port); |
| 752 | |||
| 753 | skip: | ||
| 754 | /* Free the transmit buffer page. */ | ||
| 755 | free_page((unsigned long)port->xmit.buf); | ||
| 756 | } | 738 | } |
| 757 | 739 | ||
| 758 | /** | 740 | /** |
| @@ -822,27 +804,12 @@ static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, | |||
| 822 | int count) | 804 | int count) |
| 823 | { | 805 | { |
| 824 | struct sdio_uart_port *port = tty->driver_data; | 806 | struct sdio_uart_port *port = tty->driver_data; |
| 825 | struct circ_buf *circ = &port->xmit; | 807 | int ret; |
| 826 | int c, ret = 0; | ||
| 827 | 808 | ||
| 828 | if (!port->func) | 809 | if (!port->func) |
| 829 | return -ENODEV; | 810 | return -ENODEV; |
| 830 | 811 | ||
| 831 | spin_lock(&port->write_lock); | 812 | ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock); |
| 832 | while (1) { | ||
| 833 | c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); | ||
| 834 | if (count < c) | ||
| 835 | c = count; | ||
| 836 | if (c <= 0) | ||
| 837 | break; | ||
| 838 | memcpy(circ->buf + circ->head, buf, c); | ||
| 839 | circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); | ||
| 840 | buf += c; | ||
| 841 | count -= c; | ||
| 842 | ret += c; | ||
| 843 | } | ||
| 844 | spin_unlock(&port->write_lock); | ||
| 845 | |||
| 846 | if (!(port->ier & UART_IER_THRI)) { | 813 | if (!(port->ier & UART_IER_THRI)) { |
| 847 | int err = sdio_uart_claim_func(port); | 814 | int err = sdio_uart_claim_func(port); |
| 848 | if (!err) { | 815 | if (!err) { |
| @@ -859,13 +826,13 @@ static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, | |||
| 859 | static int sdio_uart_write_room(struct tty_struct *tty) | 826 | static int sdio_uart_write_room(struct tty_struct *tty) |
| 860 | { | 827 | { |
| 861 | struct sdio_uart_port *port = tty->driver_data; | 828 | struct sdio_uart_port *port = tty->driver_data; |
| 862 | return port ? circ_chars_free(&port->xmit) : 0; | 829 | return FIFO_SIZE - kfifo_len(&port->xmit_fifo); |
| 863 | } | 830 | } |
| 864 | 831 | ||
| 865 | static int sdio_uart_chars_in_buffer(struct tty_struct *tty) | 832 | static int sdio_uart_chars_in_buffer(struct tty_struct *tty) |
| 866 | { | 833 | { |
| 867 | struct sdio_uart_port *port = tty->driver_data; | 834 | struct sdio_uart_port *port = tty->driver_data; |
| 868 | return port ? circ_chars_pending(&port->xmit) : 0; | 835 | return kfifo_len(&port->xmit_fifo); |
| 869 | } | 836 | } |
| 870 | 837 | ||
| 871 | static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) | 838 | static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index ad113b0f62db..0950fa40684f 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
| @@ -2908,6 +2908,7 @@ enum parport_pc_pci_cards { | |||
| 2908 | netmos_9805, | 2908 | netmos_9805, |
| 2909 | netmos_9815, | 2909 | netmos_9815, |
| 2910 | netmos_9901, | 2910 | netmos_9901, |
| 2911 | netmos_9865, | ||
| 2911 | quatech_sppxp100, | 2912 | quatech_sppxp100, |
| 2912 | }; | 2913 | }; |
| 2913 | 2914 | ||
| @@ -2989,6 +2990,7 @@ static struct parport_pc_pci { | |||
| 2989 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, | 2990 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, |
| 2990 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, | 2991 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, |
| 2991 | /* netmos_9901 */ { 1, { { 0, -1 }, } }, | 2992 | /* netmos_9901 */ { 1, { { 0, -1 }, } }, |
| 2993 | /* netmos_9865 */ { 1, { { 0, -1 }, } }, | ||
| 2992 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, | 2994 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, |
| 2993 | }; | 2995 | }; |
| 2994 | 2996 | ||
| @@ -3092,6 +3094,10 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
| 3092 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, | 3094 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, |
| 3093 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | 3095 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, |
| 3094 | 0xA000, 0x2000, 0, 0, netmos_9901 }, | 3096 | 0xA000, 0x2000, 0, 0, netmos_9901 }, |
| 3097 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, | ||
| 3098 | 0xA000, 0x1000, 0, 0, netmos_9865 }, | ||
| 3099 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, | ||
| 3100 | 0xA000, 0x2000, 0, 0, netmos_9865 }, | ||
| 3095 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ | 3101 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ |
| 3096 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, | 3102 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, |
| 3097 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, | 3103 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index d935b2d04f93..ae0251ef6f4e 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
| @@ -153,8 +153,6 @@ static int baud_table[] = { | |||
| 153 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 153 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
| 154 | 9600, 19200, 38400, 57600, 115200, 0 }; | 154 | 9600, 19200, 38400, 57600, 115200, 0 }; |
| 155 | 155 | ||
| 156 | #define BAUD_TABLE_SIZE (sizeof(baud_table)/sizeof(baud_table[0])) | ||
| 157 | |||
| 158 | /* Sets or clears DTR/RTS on the requested line */ | 156 | /* Sets or clears DTR/RTS on the requested line */ |
| 159 | static inline void m68k_rtsdtr(struct m68k_serial *ss, int set) | 157 | static inline void m68k_rtsdtr(struct m68k_serial *ss, int set) |
| 160 | { | 158 | { |
| @@ -1406,10 +1404,10 @@ static void m68328_set_baud(void) | |||
| 1406 | USTCNT = ustcnt & ~USTCNT_TXEN; | 1404 | USTCNT = ustcnt & ~USTCNT_TXEN; |
| 1407 | 1405 | ||
| 1408 | again: | 1406 | again: |
| 1409 | for (i = 0; i < sizeof(baud_table) / sizeof(baud_table[0]); i++) | 1407 | for (i = 0; i < ARRAY_SIZE(baud_table); i++) |
| 1410 | if (baud_table[i] == m68328_console_baud) | 1408 | if (baud_table[i] == m68328_console_baud) |
| 1411 | break; | 1409 | break; |
| 1412 | if (i >= sizeof(baud_table) / sizeof(baud_table[0])) { | 1410 | if (i >= ARRAY_SIZE(baud_table)) { |
| 1413 | m68328_console_baud = 9600; | 1411 | m68328_console_baud = 9600; |
| 1414 | goto again; | 1412 | goto again; |
| 1415 | } | 1413 | } |
| @@ -1435,7 +1433,7 @@ int m68328_console_setup(struct console *cp, char *arg) | |||
| 1435 | if (arg) | 1433 | if (arg) |
| 1436 | n = simple_strtoul(arg,NULL,0); | 1434 | n = simple_strtoul(arg,NULL,0); |
| 1437 | 1435 | ||
| 1438 | for (i = 0; i < BAUD_TABLE_SIZE; i++) | 1436 | for (i = 0; i < ARRAY_SIZE(baud_table); i++) |
| 1439 | if (baud_table[i] == n) | 1437 | if (baud_table[i] == n) |
| 1440 | break; | 1438 | break; |
| 1441 | if (i < BAUD_TABLE_SIZE) { | 1439 | if (i < BAUD_TABLE_SIZE) { |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index a81ff7bc5fa1..7c4ebe6ee18b 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
| @@ -2690,6 +2690,15 @@ static void __init serial8250_isa_init_ports(void) | |||
| 2690 | } | 2690 | } |
| 2691 | } | 2691 | } |
| 2692 | 2692 | ||
| 2693 | static void | ||
| 2694 | serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type) | ||
| 2695 | { | ||
| 2696 | up->port.type = type; | ||
| 2697 | up->port.fifosize = uart_config[type].fifo_size; | ||
| 2698 | up->capabilities = uart_config[type].flags; | ||
| 2699 | up->tx_loadsz = uart_config[type].tx_loadsz; | ||
| 2700 | } | ||
| 2701 | |||
| 2693 | static void __init | 2702 | static void __init |
| 2694 | serial8250_register_ports(struct uart_driver *drv, struct device *dev) | 2703 | serial8250_register_ports(struct uart_driver *drv, struct device *dev) |
| 2695 | { | 2704 | { |
| @@ -2706,6 +2715,10 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) | |||
| 2706 | struct uart_8250_port *up = &serial8250_ports[i]; | 2715 | struct uart_8250_port *up = &serial8250_ports[i]; |
| 2707 | 2716 | ||
| 2708 | up->port.dev = dev; | 2717 | up->port.dev = dev; |
| 2718 | |||
| 2719 | if (up->port.flags & UPF_FIXED_TYPE) | ||
| 2720 | serial8250_init_fixed_type_port(up, up->port.type); | ||
| 2721 | |||
| 2709 | uart_add_one_port(drv, &up->port); | 2722 | uart_add_one_port(drv, &up->port); |
| 2710 | } | 2723 | } |
| 2711 | } | 2724 | } |
| @@ -3118,12 +3131,8 @@ int serial8250_register_port(struct uart_port *port) | |||
| 3118 | if (port->dev) | 3131 | if (port->dev) |
| 3119 | uart->port.dev = port->dev; | 3132 | uart->port.dev = port->dev; |
| 3120 | 3133 | ||
| 3121 | if (port->flags & UPF_FIXED_TYPE) { | 3134 | if (port->flags & UPF_FIXED_TYPE) |
| 3122 | uart->port.type = port->type; | 3135 | serial8250_init_fixed_type_port(uart, port->type); |
| 3123 | uart->port.fifosize = uart_config[port->type].fifo_size; | ||
| 3124 | uart->capabilities = uart_config[port->type].flags; | ||
| 3125 | uart->tx_loadsz = uart_config[port->type].tx_loadsz; | ||
| 3126 | } | ||
| 3127 | 3136 | ||
| 3128 | set_io_from_upio(&uart->port); | 3137 | set_io_from_upio(&uart->port); |
| 3129 | /* Possibly override default I/O functions. */ | 3138 | /* Possibly override default I/O functions. */ |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index b28af13c45a1..01c012da4e26 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
| @@ -760,7 +760,8 @@ static int pci_netmos_init(struct pci_dev *dev) | |||
| 760 | /* subdevice 0x00PS means <P> parallel, <S> serial */ | 760 | /* subdevice 0x00PS means <P> parallel, <S> serial */ |
| 761 | unsigned int num_serial = dev->subsystem_device & 0xf; | 761 | unsigned int num_serial = dev->subsystem_device & 0xf; |
| 762 | 762 | ||
| 763 | if (dev->device == PCI_DEVICE_ID_NETMOS_9901) | 763 | if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) || |
| 764 | (dev->device == PCI_DEVICE_ID_NETMOS_9865)) | ||
| 764 | return 0; | 765 | return 0; |
| 765 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && | 766 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && |
| 766 | dev->subsystem_device == 0x0299) | 767 | dev->subsystem_device == 0x0299) |
| @@ -1479,6 +1480,7 @@ enum pci_board_num_t { | |||
| 1479 | 1480 | ||
| 1480 | pbn_b0_bt_1_115200, | 1481 | pbn_b0_bt_1_115200, |
| 1481 | pbn_b0_bt_2_115200, | 1482 | pbn_b0_bt_2_115200, |
| 1483 | pbn_b0_bt_4_115200, | ||
| 1482 | pbn_b0_bt_8_115200, | 1484 | pbn_b0_bt_8_115200, |
| 1483 | 1485 | ||
| 1484 | pbn_b0_bt_1_460800, | 1486 | pbn_b0_bt_1_460800, |
| @@ -1703,6 +1705,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { | |||
| 1703 | .base_baud = 115200, | 1705 | .base_baud = 115200, |
| 1704 | .uart_offset = 8, | 1706 | .uart_offset = 8, |
| 1705 | }, | 1707 | }, |
| 1708 | [pbn_b0_bt_4_115200] = { | ||
| 1709 | .flags = FL_BASE0|FL_BASE_BARS, | ||
| 1710 | .num_ports = 4, | ||
| 1711 | .base_baud = 115200, | ||
| 1712 | .uart_offset = 8, | ||
| 1713 | }, | ||
| 1706 | [pbn_b0_bt_8_115200] = { | 1714 | [pbn_b0_bt_8_115200] = { |
| 1707 | .flags = FL_BASE0|FL_BASE_BARS, | 1715 | .flags = FL_BASE0|FL_BASE_BARS, |
| 1708 | .num_ports = 8, | 1716 | .num_ports = 8, |
| @@ -3191,6 +3199,15 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
| 3191 | 0x1208, 0x0004, 0, 0, | 3199 | 0x1208, 0x0004, 0, 0, |
| 3192 | pbn_b0_4_921600 }, | 3200 | pbn_b0_4_921600 }, |
| 3193 | 3201 | ||
| 3202 | { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2, | ||
| 3203 | 0x1204, 0x0004, 0, 0, | ||
| 3204 | pbn_b0_4_921600 }, | ||
| 3205 | { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2, | ||
| 3206 | 0x1208, 0x0004, 0, 0, | ||
| 3207 | pbn_b0_4_921600 }, | ||
| 3208 | { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3, | ||
| 3209 | 0x1208, 0x0004, 0, 0, | ||
| 3210 | pbn_b0_4_921600 }, | ||
| 3194 | /* | 3211 | /* |
| 3195 | * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com | 3212 | * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com |
| 3196 | */ | 3213 | */ |
| @@ -3649,6 +3666,18 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
| 3649 | 0, 0, pbn_b0_1_115200 }, | 3666 | 0, 0, pbn_b0_1_115200 }, |
| 3650 | 3667 | ||
| 3651 | /* | 3668 | /* |
| 3669 | * Best Connectivity PCI Multi I/O cards | ||
| 3670 | */ | ||
| 3671 | |||
| 3672 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, | ||
| 3673 | 0xA000, 0x1000, | ||
| 3674 | 0, 0, pbn_b0_1_115200 }, | ||
| 3675 | |||
| 3676 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, | ||
| 3677 | 0xA000, 0x3004, | ||
| 3678 | 0, 0, pbn_b0_bt_4_115200 }, | ||
| 3679 | |||
| 3680 | /* | ||
| 3652 | * These entries match devices with class COMMUNICATION_SERIAL, | 3681 | * These entries match devices with class COMMUNICATION_SERIAL, |
| 3653 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL | 3682 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL |
| 3654 | */ | 3683 | */ |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 888a0ce91c4b..746e07033dce 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -1418,42 +1418,37 @@ config SERIAL_BFIN_SPORT | |||
| 1418 | To compile this driver as a module, choose M here: the | 1418 | To compile this driver as a module, choose M here: the |
| 1419 | module will be called bfin_sport_uart. | 1419 | module will be called bfin_sport_uart. |
| 1420 | 1420 | ||
| 1421 | choice | 1421 | config SERIAL_BFIN_SPORT_CONSOLE |
| 1422 | prompt "Baud rate for Blackfin SPORT UART" | 1422 | bool "Console on Blackfin sport emulated uart" |
| 1423 | depends on SERIAL_BFIN_SPORT | 1423 | depends on SERIAL_BFIN_SPORT=y |
| 1424 | default SERIAL_SPORT_BAUD_RATE_57600 | 1424 | select SERIAL_CORE_CONSOLE |
| 1425 | help | ||
| 1426 | Choose a baud rate for the SPORT UART, other uart settings are | ||
| 1427 | 8 bit, 1 stop bit, no parity, no flow control. | ||
| 1428 | |||
| 1429 | config SERIAL_SPORT_BAUD_RATE_115200 | ||
| 1430 | bool "115200" | ||
| 1431 | |||
| 1432 | config SERIAL_SPORT_BAUD_RATE_57600 | ||
| 1433 | bool "57600" | ||
| 1434 | 1425 | ||
| 1435 | config SERIAL_SPORT_BAUD_RATE_38400 | 1426 | config SERIAL_BFIN_SPORT0_UART |
| 1436 | bool "38400" | 1427 | bool "Enable UART over SPORT0" |
| 1428 | depends on SERIAL_BFIN_SPORT && !(BF542 || BF542M || BF544 || BF544M) | ||
| 1429 | help | ||
| 1430 | Enable UART over SPORT0 | ||
| 1437 | 1431 | ||
| 1438 | config SERIAL_SPORT_BAUD_RATE_19200 | 1432 | config SERIAL_BFIN_SPORT1_UART |
| 1439 | bool "19200" | 1433 | bool "Enable UART over SPORT1" |
| 1434 | depends on SERIAL_BFIN_SPORT | ||
| 1435 | help | ||
| 1436 | Enable UART over SPORT1 | ||
| 1440 | 1437 | ||
| 1441 | config SERIAL_SPORT_BAUD_RATE_9600 | 1438 | config SERIAL_BFIN_SPORT2_UART |
| 1442 | bool "9600" | 1439 | bool "Enable UART over SPORT2" |
| 1443 | endchoice | 1440 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) |
| 1441 | help | ||
| 1442 | Enable UART over SPORT2 | ||
| 1444 | 1443 | ||
| 1445 | config SPORT_BAUD_RATE | 1444 | config SERIAL_BFIN_SPORT3_UART |
| 1446 | int | 1445 | bool "Enable UART over SPORT3" |
| 1447 | depends on SERIAL_BFIN_SPORT | 1446 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) |
| 1448 | default 115200 if (SERIAL_SPORT_BAUD_RATE_115200) | 1447 | help |
| 1449 | default 57600 if (SERIAL_SPORT_BAUD_RATE_57600) | 1448 | Enable UART over SPORT3 |
| 1450 | default 38400 if (SERIAL_SPORT_BAUD_RATE_38400) | ||
| 1451 | default 19200 if (SERIAL_SPORT_BAUD_RATE_19200) | ||
| 1452 | default 9600 if (SERIAL_SPORT_BAUD_RATE_9600) | ||
| 1453 | 1449 | ||
| 1454 | config SERIAL_TIMBERDALE | 1450 | config SERIAL_TIMBERDALE |
| 1455 | tristate "Support for timberdale UART" | 1451 | tristate "Support for timberdale UART" |
| 1456 | depends on MFD_TIMBERDALE | ||
| 1457 | select SERIAL_CORE | 1452 | select SERIAL_CORE |
| 1458 | ---help--- | 1453 | ---help--- |
| 1459 | Add support for UART controller on timberdale. | 1454 | Add support for UART controller on timberdale. |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 9d948bccafaf..2c9bf9b68327 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
| @@ -1213,6 +1213,24 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
| 1213 | return ret; | 1213 | return ret; |
| 1214 | } | 1214 | } |
| 1215 | 1215 | ||
| 1216 | #ifdef CONFIG_CONSOLE_POLL | ||
| 1217 | static int atmel_poll_get_char(struct uart_port *port) | ||
| 1218 | { | ||
| 1219 | while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY)) | ||
| 1220 | cpu_relax(); | ||
| 1221 | |||
| 1222 | return UART_GET_CHAR(port); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) | ||
| 1226 | { | ||
| 1227 | while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY)) | ||
| 1228 | cpu_relax(); | ||
| 1229 | |||
| 1230 | UART_PUT_CHAR(port, ch); | ||
| 1231 | } | ||
| 1232 | #endif | ||
| 1233 | |||
| 1216 | static struct uart_ops atmel_pops = { | 1234 | static struct uart_ops atmel_pops = { |
| 1217 | .tx_empty = atmel_tx_empty, | 1235 | .tx_empty = atmel_tx_empty, |
| 1218 | .set_mctrl = atmel_set_mctrl, | 1236 | .set_mctrl = atmel_set_mctrl, |
| @@ -1232,6 +1250,10 @@ static struct uart_ops atmel_pops = { | |||
| 1232 | .config_port = atmel_config_port, | 1250 | .config_port = atmel_config_port, |
| 1233 | .verify_port = atmel_verify_port, | 1251 | .verify_port = atmel_verify_port, |
| 1234 | .pm = atmel_serial_pm, | 1252 | .pm = atmel_serial_pm, |
| 1253 | #ifdef CONFIG_CONSOLE_POLL | ||
| 1254 | .poll_get_char = atmel_poll_get_char, | ||
| 1255 | .poll_put_char = atmel_poll_put_char, | ||
| 1256 | #endif | ||
| 1235 | }; | 1257 | }; |
| 1236 | 1258 | ||
| 1237 | /* | 1259 | /* |
diff --git a/drivers/serial/bcm63xx_uart.c b/drivers/serial/bcm63xx_uart.c index 37ad0c449937..a1a0e55d0807 100644 --- a/drivers/serial/bcm63xx_uart.c +++ b/drivers/serial/bcm63xx_uart.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | #include <bcm63xx_regs.h> | 35 | #include <bcm63xx_regs.h> |
| 36 | #include <bcm63xx_io.h> | 36 | #include <bcm63xx_io.h> |
| 37 | 37 | ||
| 38 | #define BCM63XX_NR_UARTS 1 | 38 | #define BCM63XX_NR_UARTS 2 |
| 39 | 39 | ||
| 40 | static struct uart_port ports[BCM63XX_NR_UARTS]; | 40 | static struct uart_port ports[BCM63XX_NR_UARTS]; |
| 41 | 41 | ||
| @@ -784,7 +784,7 @@ static struct uart_driver bcm_uart_driver = { | |||
| 784 | .dev_name = "ttyS", | 784 | .dev_name = "ttyS", |
| 785 | .major = TTY_MAJOR, | 785 | .major = TTY_MAJOR, |
| 786 | .minor = 64, | 786 | .minor = 64, |
| 787 | .nr = 1, | 787 | .nr = BCM63XX_NR_UARTS, |
| 788 | .cons = BCM63XX_CONSOLE, | 788 | .cons = BCM63XX_CONSOLE, |
| 789 | }; | 789 | }; |
| 790 | 790 | ||
| @@ -826,11 +826,12 @@ static int __devinit bcm_uart_probe(struct platform_device *pdev) | |||
| 826 | port->dev = &pdev->dev; | 826 | port->dev = &pdev->dev; |
| 827 | port->fifosize = 16; | 827 | port->fifosize = 16; |
| 828 | port->uartclk = clk_get_rate(clk) / 2; | 828 | port->uartclk = clk_get_rate(clk) / 2; |
| 829 | port->line = pdev->id; | ||
| 829 | clk_put(clk); | 830 | clk_put(clk); |
| 830 | 831 | ||
| 831 | ret = uart_add_one_port(&bcm_uart_driver, port); | 832 | ret = uart_add_one_port(&bcm_uart_driver, port); |
| 832 | if (ret) { | 833 | if (ret) { |
| 833 | kfree(port); | 834 | ports[pdev->id].membase = 0; |
| 834 | return ret; | 835 | return ret; |
| 835 | } | 836 | } |
| 836 | platform_set_drvdata(pdev, port); | 837 | platform_set_drvdata(pdev, port); |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 50abb7e557f4..fcf273e3f48c 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
| 17 | #include <linux/io.h> | ||
| 17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 18 | #include <linux/console.h> | 19 | #include <linux/console.h> |
| 19 | #include <linux/sysrq.h> | 20 | #include <linux/sysrq.h> |
| @@ -237,7 +238,8 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
| 237 | 238 | ||
| 238 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | 239 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
| 239 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | 240 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) |
| 240 | if (kgdb_connected && kgdboc_port_line == uart->port.line) | 241 | if (kgdb_connected && kgdboc_port_line == uart->port.line |
| 242 | && kgdboc_break_enabled) | ||
| 241 | if (ch == 0x3) {/* Ctrl + C */ | 243 | if (ch == 0x3) {/* Ctrl + C */ |
| 242 | kgdb_breakpoint(); | 244 | kgdb_breakpoint(); |
| 243 | return; | 245 | return; |
| @@ -488,6 +490,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | |||
| 488 | { | 490 | { |
| 489 | int x_pos, pos; | 491 | int x_pos, pos; |
| 490 | 492 | ||
| 493 | dma_disable_irq(uart->tx_dma_channel); | ||
| 491 | dma_disable_irq(uart->rx_dma_channel); | 494 | dma_disable_irq(uart->rx_dma_channel); |
| 492 | spin_lock_bh(&uart->port.lock); | 495 | spin_lock_bh(&uart->port.lock); |
| 493 | 496 | ||
| @@ -521,6 +524,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | |||
| 521 | } | 524 | } |
| 522 | 525 | ||
| 523 | spin_unlock_bh(&uart->port.lock); | 526 | spin_unlock_bh(&uart->port.lock); |
| 527 | dma_enable_irq(uart->tx_dma_channel); | ||
| 524 | dma_enable_irq(uart->rx_dma_channel); | 528 | dma_enable_irq(uart->rx_dma_channel); |
| 525 | 529 | ||
| 526 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); | 530 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); |
| @@ -746,15 +750,6 @@ static int bfin_serial_startup(struct uart_port *port) | |||
| 746 | Status interrupt.\n"); | 750 | Status interrupt.\n"); |
| 747 | } | 751 | } |
| 748 | 752 | ||
| 749 | if (uart->cts_pin >= 0) { | ||
| 750 | gpio_request(uart->cts_pin, DRIVER_NAME); | ||
| 751 | gpio_direction_output(uart->cts_pin, 1); | ||
| 752 | } | ||
| 753 | if (uart->rts_pin >= 0) { | ||
| 754 | gpio_request(uart->rts_pin, DRIVER_NAME); | ||
| 755 | gpio_direction_output(uart->rts_pin, 0); | ||
| 756 | } | ||
| 757 | |||
| 758 | /* CTS RTS PINs are negative assertive. */ | 753 | /* CTS RTS PINs are negative assertive. */ |
| 759 | UART_PUT_MCR(uart, ACTS); | 754 | UART_PUT_MCR(uart, ACTS); |
| 760 | UART_SET_IER(uart, EDSSI); | 755 | UART_SET_IER(uart, EDSSI); |
| @@ -801,10 +796,6 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
| 801 | gpio_free(uart->rts_pin); | 796 | gpio_free(uart->rts_pin); |
| 802 | #endif | 797 | #endif |
| 803 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | 798 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
| 804 | if (uart->cts_pin >= 0) | ||
| 805 | gpio_free(uart->cts_pin); | ||
| 806 | if (uart->rts_pin >= 0) | ||
| 807 | gpio_free(uart->rts_pin); | ||
| 808 | if (UART_GET_IER(uart) && EDSSI) | 799 | if (UART_GET_IER(uart) && EDSSI) |
| 809 | free_irq(uart->status_irq, uart); | 800 | free_irq(uart->status_irq, uart); |
| 810 | #endif | 801 | #endif |
| @@ -1409,8 +1400,7 @@ static int bfin_serial_remove(struct platform_device *dev) | |||
| 1409 | continue; | 1400 | continue; |
| 1410 | uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); | 1401 | uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); |
| 1411 | bfin_serial_ports[i].port.dev = NULL; | 1402 | bfin_serial_ports[i].port.dev = NULL; |
| 1412 | #if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \ | 1403 | #if defined(CONFIG_SERIAL_BFIN_CTSRTS) |
| 1413 | defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS) | ||
| 1414 | gpio_free(bfin_serial_ports[i].cts_pin); | 1404 | gpio_free(bfin_serial_ports[i].cts_pin); |
| 1415 | gpio_free(bfin_serial_ports[i].rts_pin); | 1405 | gpio_free(bfin_serial_ports[i].rts_pin); |
| 1416 | #endif | 1406 | #endif |
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index 088bb35475f1..7c72888fbf94 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
| @@ -1,27 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * File: linux/drivers/serial/bfin_sport_uart.c | 2 | * Blackfin On-Chip Sport Emulated UART Driver |
| 3 | * | 3 | * |
| 4 | * Based on: drivers/serial/bfin_5xx.c by Aubrey Li. | 4 | * Copyright 2006-2009 Analog Devices Inc. |
| 5 | * Author: Roy Huang <roy.huang@analog.com> | ||
| 6 | * | 5 | * |
| 7 | * Created: Nov 22, 2006 | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
| 8 | * Copyright: (c) 2006-2007 Analog Devices Inc. | ||
| 9 | * Description: this driver enable SPORTs on Blackfin emulate UART. | ||
| 10 | * | 7 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 8 | * Licensed under the GPL-2 or later. |
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, see the file COPYING, or write | ||
| 23 | * to the Free Software Foundation, Inc., | ||
| 24 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 25 | */ | 9 | */ |
| 26 | 10 | ||
| 27 | /* | 11 | /* |
| @@ -29,39 +13,18 @@ | |||
| 29 | * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf | 13 | * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf |
| 30 | * This application note describe how to implement a UART on a Sharc DSP, | 14 | * This application note describe how to implement a UART on a Sharc DSP, |
| 31 | * but this driver is implemented on Blackfin Processor. | 15 | * but this driver is implemented on Blackfin Processor. |
| 16 | * Transmit Frame Sync is not used by this driver to transfer data out. | ||
| 32 | */ | 17 | */ |
| 33 | 18 | ||
| 34 | /* After reset, there is a prelude of low level pulse when transmit data first | 19 | /* #define DEBUG */ |
| 35 | * time. No addtional pulse in following transmit. | ||
| 36 | * According to document: | ||
| 37 | * The SPORTs are ready to start transmitting or receiving data no later than | ||
| 38 | * three serial clock cycles after they are enabled in the SPORTx_TCR1 or | ||
| 39 | * SPORTx_RCR1 register. No serial clock cycles are lost from this point on. | ||
| 40 | * The first internal frame sync will occur one frame sync delay after the | ||
| 41 | * SPORTs are ready. External frame syncs can occur as soon as the SPORT is | ||
| 42 | * ready. | ||
| 43 | */ | ||
| 44 | 20 | ||
| 45 | /* Thanks to Axel Alatalo <axel@rubico.se> for fixing sport rx bug. Sometimes | 21 | #define DRV_NAME "bfin-sport-uart" |
| 46 | * sport receives data incorrectly. The following is Axel's words. | 22 | #define DEVICE_NAME "ttySS" |
| 47 | * As EE-191, sport rx samples 3 times of the UART baudrate and takes the | 23 | #define pr_fmt(fmt) DRV_NAME ": " fmt |
| 48 | * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting, | ||
| 49 | * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short | ||
| 50 | * byte due to buadrate drift, then the 30th sample of a byte, this sample is | ||
| 51 | * also the third sample of the stop bit, will happens on the immediately | ||
| 52 | * following start bit which will be thrown away and missed. Thus since parts | ||
| 53 | * of the startbit will be missed and the receiver will begin to drift, the | ||
| 54 | * effect accumulates over time until synchronization is lost. | ||
| 55 | * If only require 2 samples of the stopbit (by sampling in total 29 samples), | ||
| 56 | * then a to short byte as in the case above will be tolerated. Then the 1/3 | ||
| 57 | * early startbit will trigger a framesync since the last read is complete | ||
| 58 | * after only 2/3 stopbit and framesync is active during the last 1/3 looking | ||
| 59 | * for a possible early startbit. */ | ||
| 60 | |||
| 61 | //#define DEBUG | ||
| 62 | 24 | ||
| 63 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 64 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
| 27 | #include <linux/io.h> | ||
| 65 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 66 | #include <linux/console.h> | 29 | #include <linux/console.h> |
| 67 | #include <linux/sysrq.h> | 30 | #include <linux/sysrq.h> |
| @@ -75,23 +38,36 @@ | |||
| 75 | 38 | ||
| 76 | #include "bfin_sport_uart.h" | 39 | #include "bfin_sport_uart.h" |
| 77 | 40 | ||
| 41 | #ifdef CONFIG_SERIAL_BFIN_SPORT0_UART | ||
| 78 | unsigned short bfin_uart_pin_req_sport0[] = | 42 | unsigned short bfin_uart_pin_req_sport0[] = |
| 79 | {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \ | 43 | {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \ |
| 80 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0}; | 44 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0}; |
| 81 | 45 | #endif | |
| 46 | #ifdef CONFIG_SERIAL_BFIN_SPORT1_UART | ||
| 82 | unsigned short bfin_uart_pin_req_sport1[] = | 47 | unsigned short bfin_uart_pin_req_sport1[] = |
| 83 | {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \ | 48 | {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \ |
| 84 | P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0}; | 49 | P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0}; |
| 85 | 50 | #endif | |
| 86 | #define DRV_NAME "bfin-sport-uart" | 51 | #ifdef CONFIG_SERIAL_BFIN_SPORT2_UART |
| 52 | unsigned short bfin_uart_pin_req_sport2[] = | ||
| 53 | {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, \ | ||
| 54 | P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0}; | ||
| 55 | #endif | ||
| 56 | #ifdef CONFIG_SERIAL_BFIN_SPORT3_UART | ||
| 57 | unsigned short bfin_uart_pin_req_sport3[] = | ||
| 58 | {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, \ | ||
| 59 | P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0}; | ||
| 60 | #endif | ||
| 87 | 61 | ||
| 88 | struct sport_uart_port { | 62 | struct sport_uart_port { |
| 89 | struct uart_port port; | 63 | struct uart_port port; |
| 90 | char *name; | ||
| 91 | |||
| 92 | int tx_irq; | ||
| 93 | int rx_irq; | ||
| 94 | int err_irq; | 64 | int err_irq; |
| 65 | unsigned short csize; | ||
| 66 | unsigned short rxmask; | ||
| 67 | unsigned short txmask1; | ||
| 68 | unsigned short txmask2; | ||
| 69 | unsigned char stopb; | ||
| 70 | /* unsigned char parib; */ | ||
| 95 | }; | 71 | }; |
| 96 | 72 | ||
| 97 | static void sport_uart_tx_chars(struct sport_uart_port *up); | 73 | static void sport_uart_tx_chars(struct sport_uart_port *up); |
| @@ -99,36 +75,42 @@ static void sport_stop_tx(struct uart_port *port); | |||
| 99 | 75 | ||
| 100 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | 76 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) |
| 101 | { | 77 | { |
| 102 | pr_debug("%s value:%x\n", __func__, value); | 78 | pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value, |
| 103 | /* Place a Start and Stop bit */ | 79 | up->txmask1, up->txmask2); |
| 80 | |||
| 81 | /* Place Start and Stop bits */ | ||
| 104 | __asm__ __volatile__ ( | 82 | __asm__ __volatile__ ( |
| 105 | "R2 = b#01111111100;" | 83 | "%[val] <<= 1;" |
| 106 | "R3 = b#10000000001;" | 84 | "%[val] = %[val] & %[mask1];" |
| 107 | "%0 <<= 2;" | 85 | "%[val] = %[val] | %[mask2];" |
| 108 | "%0 = %0 & R2;" | 86 | : [val]"+d"(value) |
| 109 | "%0 = %0 | R3;" | 87 | : [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2) |
| 110 | : "=d"(value) | 88 | : "ASTAT" |
| 111 | : "d"(value) | ||
| 112 | : "ASTAT", "R2", "R3" | ||
| 113 | ); | 89 | ); |
| 114 | pr_debug("%s value:%x\n", __func__, value); | 90 | pr_debug("%s value:%x\n", __func__, value); |
| 115 | 91 | ||
| 116 | SPORT_PUT_TX(up, value); | 92 | SPORT_PUT_TX(up, value); |
| 117 | } | 93 | } |
| 118 | 94 | ||
| 119 | static inline unsigned int rx_one_byte(struct sport_uart_port *up) | 95 | static inline unsigned char rx_one_byte(struct sport_uart_port *up) |
| 120 | { | 96 | { |
| 121 | unsigned int value, extract; | 97 | unsigned int value; |
| 98 | unsigned char extract; | ||
| 122 | u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; | 99 | u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; |
| 123 | 100 | ||
| 124 | value = SPORT_GET_RX32(up); | 101 | if ((up->csize + up->stopb) > 7) |
| 125 | pr_debug("%s value:%x\n", __func__, value); | 102 | value = SPORT_GET_RX32(up); |
| 103 | else | ||
| 104 | value = SPORT_GET_RX(up); | ||
| 105 | |||
| 106 | pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value, | ||
| 107 | up->csize, up->rxmask); | ||
| 126 | 108 | ||
| 127 | /* Extract 8 bits data */ | 109 | /* Extract data */ |
| 128 | __asm__ __volatile__ ( | 110 | __asm__ __volatile__ ( |
| 129 | "%[extr] = 0;" | 111 | "%[extr] = 0;" |
| 130 | "%[mask1] = 0x1801(Z);" | 112 | "%[mask1] = %[rxmask];" |
| 131 | "%[mask2] = 0x0300(Z);" | 113 | "%[mask2] = 0x0200(Z);" |
| 132 | "%[shift] = 0;" | 114 | "%[shift] = 0;" |
| 133 | "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" | 115 | "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" |
| 134 | ".Lloop_s:" | 116 | ".Lloop_s:" |
| @@ -138,9 +120,9 @@ static inline unsigned int rx_one_byte(struct sport_uart_port *up) | |||
| 138 | "%[mask1] = %[mask1] - %[mask2];" | 120 | "%[mask1] = %[mask1] - %[mask2];" |
| 139 | ".Lloop_e:" | 121 | ".Lloop_e:" |
| 140 | "%[shift] += 1;" | 122 | "%[shift] += 1;" |
| 141 | : [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp), | 123 | : [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp), |
| 142 | [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2) | 124 | [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2) |
| 143 | : "d"(value), [lc]"a"(8) | 125 | : [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize) |
| 144 | : "ASTAT", "LB0", "LC0", "LT0" | 126 | : "ASTAT", "LB0", "LC0", "LT0" |
| 145 | ); | 127 | ); |
| 146 | 128 | ||
| @@ -148,29 +130,28 @@ static inline unsigned int rx_one_byte(struct sport_uart_port *up) | |||
| 148 | return extract; | 130 | return extract; |
| 149 | } | 131 | } |
| 150 | 132 | ||
| 151 | static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate) | 133 | static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) |
| 152 | { | 134 | { |
| 153 | int tclkdiv, tfsdiv, rclkdiv; | 135 | int tclkdiv, rclkdiv; |
| 136 | unsigned int sclk = get_sclk(); | ||
| 154 | 137 | ||
| 155 | /* Set TCR1 and TCR2 */ | 138 | /* Set TCR1 and TCR2, TFSR is not enabled for uart */ |
| 156 | SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); | 139 | SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK)); |
| 157 | SPORT_PUT_TCR2(up, 10); | 140 | SPORT_PUT_TCR2(up, size + 1); |
| 158 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); | 141 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); |
| 159 | 142 | ||
| 160 | /* Set RCR1 and RCR2 */ | 143 | /* Set RCR1 and RCR2 */ |
| 161 | SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); | 144 | SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); |
| 162 | SPORT_PUT_RCR2(up, 28); | 145 | SPORT_PUT_RCR2(up, (size + 1) * 2 - 1); |
| 163 | pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); | 146 | pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); |
| 164 | 147 | ||
| 165 | tclkdiv = sclk/(2 * baud_rate) - 1; | 148 | tclkdiv = sclk / (2 * baud_rate) - 1; |
| 166 | tfsdiv = 12; | 149 | rclkdiv = sclk / (2 * baud_rate * 2) - 1; |
| 167 | rclkdiv = sclk/(2 * baud_rate * 3) - 1; | ||
| 168 | SPORT_PUT_TCLKDIV(up, tclkdiv); | 150 | SPORT_PUT_TCLKDIV(up, tclkdiv); |
| 169 | SPORT_PUT_TFSDIV(up, tfsdiv); | ||
| 170 | SPORT_PUT_RCLKDIV(up, rclkdiv); | 151 | SPORT_PUT_RCLKDIV(up, rclkdiv); |
| 171 | SSYNC(); | 152 | SSYNC(); |
| 172 | pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n", | 153 | pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n", |
| 173 | __func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv); | 154 | __func__, sclk, baud_rate, tclkdiv, rclkdiv); |
| 174 | 155 | ||
| 175 | return 0; | 156 | return 0; |
| 176 | } | 157 | } |
| @@ -181,23 +162,29 @@ static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id) | |||
| 181 | struct tty_struct *tty = up->port.state->port.tty; | 162 | struct tty_struct *tty = up->port.state->port.tty; |
| 182 | unsigned int ch; | 163 | unsigned int ch; |
| 183 | 164 | ||
| 184 | do { | 165 | spin_lock(&up->port.lock); |
| 166 | |||
| 167 | while (SPORT_GET_STAT(up) & RXNE) { | ||
| 185 | ch = rx_one_byte(up); | 168 | ch = rx_one_byte(up); |
| 186 | up->port.icount.rx++; | 169 | up->port.icount.rx++; |
| 187 | 170 | ||
| 188 | if (uart_handle_sysrq_char(&up->port, ch)) | 171 | if (!uart_handle_sysrq_char(&up->port, ch)) |
| 189 | ; | ||
| 190 | else | ||
| 191 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | 172 | tty_insert_flip_char(tty, ch, TTY_NORMAL); |
| 192 | } while (SPORT_GET_STAT(up) & RXNE); | 173 | } |
| 193 | tty_flip_buffer_push(tty); | 174 | tty_flip_buffer_push(tty); |
| 194 | 175 | ||
| 176 | spin_unlock(&up->port.lock); | ||
| 177 | |||
| 195 | return IRQ_HANDLED; | 178 | return IRQ_HANDLED; |
| 196 | } | 179 | } |
| 197 | 180 | ||
| 198 | static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id) | 181 | static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id) |
| 199 | { | 182 | { |
| 200 | sport_uart_tx_chars(dev_id); | 183 | struct sport_uart_port *up = dev_id; |
| 184 | |||
| 185 | spin_lock(&up->port.lock); | ||
| 186 | sport_uart_tx_chars(up); | ||
| 187 | spin_unlock(&up->port.lock); | ||
| 201 | 188 | ||
| 202 | return IRQ_HANDLED; | 189 | return IRQ_HANDLED; |
| 203 | } | 190 | } |
| @@ -208,6 +195,8 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
| 208 | struct tty_struct *tty = up->port.state->port.tty; | 195 | struct tty_struct *tty = up->port.state->port.tty; |
| 209 | unsigned int stat = SPORT_GET_STAT(up); | 196 | unsigned int stat = SPORT_GET_STAT(up); |
| 210 | 197 | ||
| 198 | spin_lock(&up->port.lock); | ||
| 199 | |||
| 211 | /* Overflow in RX FIFO */ | 200 | /* Overflow in RX FIFO */ |
| 212 | if (stat & ROVF) { | 201 | if (stat & ROVF) { |
| 213 | up->port.icount.overrun++; | 202 | up->port.icount.overrun++; |
| @@ -216,15 +205,16 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
| 216 | } | 205 | } |
| 217 | /* These should not happen */ | 206 | /* These should not happen */ |
| 218 | if (stat & (TOVF | TUVF | RUVF)) { | 207 | if (stat & (TOVF | TUVF | RUVF)) { |
| 219 | printk(KERN_ERR "SPORT Error:%s %s %s\n", | 208 | pr_err("SPORT Error:%s %s %s\n", |
| 220 | (stat & TOVF)?"TX overflow":"", | 209 | (stat & TOVF) ? "TX overflow" : "", |
| 221 | (stat & TUVF)?"TX underflow":"", | 210 | (stat & TUVF) ? "TX underflow" : "", |
| 222 | (stat & RUVF)?"RX underflow":""); | 211 | (stat & RUVF) ? "RX underflow" : ""); |
| 223 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); | 212 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); |
| 224 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); | 213 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); |
| 225 | } | 214 | } |
| 226 | SSYNC(); | 215 | SSYNC(); |
| 227 | 216 | ||
| 217 | spin_unlock(&up->port.lock); | ||
| 228 | return IRQ_HANDLED; | 218 | return IRQ_HANDLED; |
| 229 | } | 219 | } |
| 230 | 220 | ||
| @@ -232,60 +222,37 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
| 232 | static int sport_startup(struct uart_port *port) | 222 | static int sport_startup(struct uart_port *port) |
| 233 | { | 223 | { |
| 234 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 224 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
| 235 | char buffer[20]; | 225 | int ret; |
| 236 | int retval; | ||
| 237 | 226 | ||
| 238 | pr_debug("%s enter\n", __func__); | 227 | pr_debug("%s enter\n", __func__); |
| 239 | snprintf(buffer, 20, "%s rx", up->name); | 228 | ret = request_irq(up->port.irq, sport_uart_rx_irq, 0, |
| 240 | retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 229 | "SPORT_UART_RX", up); |
| 241 | if (retval) { | 230 | if (ret) { |
| 242 | printk(KERN_ERR "Unable to request interrupt %s\n", buffer); | 231 | dev_err(port->dev, "unable to request SPORT RX interrupt\n"); |
| 243 | return retval; | 232 | return ret; |
| 244 | } | 233 | } |
| 245 | 234 | ||
| 246 | snprintf(buffer, 20, "%s tx", up->name); | 235 | ret = request_irq(up->port.irq+1, sport_uart_tx_irq, 0, |
| 247 | retval = request_irq(up->tx_irq, sport_uart_tx_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 236 | "SPORT_UART_TX", up); |
| 248 | if (retval) { | 237 | if (ret) { |
| 249 | printk(KERN_ERR "Unable to request interrupt %s\n", buffer); | 238 | dev_err(port->dev, "unable to request SPORT TX interrupt\n"); |
| 250 | goto fail1; | 239 | goto fail1; |
| 251 | } | 240 | } |
| 252 | 241 | ||
| 253 | snprintf(buffer, 20, "%s err", up->name); | 242 | ret = request_irq(up->err_irq, sport_uart_err_irq, 0, |
| 254 | retval = request_irq(up->err_irq, sport_uart_err_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 243 | "SPORT_UART_STATUS", up); |
| 255 | if (retval) { | 244 | if (ret) { |
| 256 | printk(KERN_ERR "Unable to request interrupt %s\n", buffer); | 245 | dev_err(port->dev, "unable to request SPORT status interrupt\n"); |
| 257 | goto fail2; | 246 | goto fail2; |
| 258 | } | 247 | } |
| 259 | 248 | ||
| 260 | if (port->line) { | ||
| 261 | if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME)) | ||
| 262 | goto fail3; | ||
| 263 | } else { | ||
| 264 | if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME)) | ||
| 265 | goto fail3; | ||
| 266 | } | ||
| 267 | |||
| 268 | sport_uart_setup(up, get_sclk(), port->uartclk); | ||
| 269 | |||
| 270 | /* Enable receive interrupt */ | ||
| 271 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN)); | ||
| 272 | SSYNC(); | ||
| 273 | |||
| 274 | return 0; | 249 | return 0; |
| 250 | fail2: | ||
| 251 | free_irq(up->port.irq+1, up); | ||
| 252 | fail1: | ||
| 253 | free_irq(up->port.irq, up); | ||
| 275 | 254 | ||
| 276 | 255 | return ret; | |
| 277 | fail3: | ||
| 278 | printk(KERN_ERR DRV_NAME | ||
| 279 | ": Requesting Peripherals failed\n"); | ||
| 280 | |||
| 281 | free_irq(up->err_irq, up); | ||
| 282 | fail2: | ||
| 283 | free_irq(up->tx_irq, up); | ||
| 284 | fail1: | ||
| 285 | free_irq(up->rx_irq, up); | ||
| 286 | |||
| 287 | return retval; | ||
| 288 | |||
| 289 | } | 256 | } |
| 290 | 257 | ||
| 291 | static void sport_uart_tx_chars(struct sport_uart_port *up) | 258 | static void sport_uart_tx_chars(struct sport_uart_port *up) |
| @@ -344,20 +311,17 @@ static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
| 344 | static void sport_stop_tx(struct uart_port *port) | 311 | static void sport_stop_tx(struct uart_port *port) |
| 345 | { | 312 | { |
| 346 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 313 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
| 347 | unsigned int stat; | ||
| 348 | 314 | ||
| 349 | pr_debug("%s enter\n", __func__); | 315 | pr_debug("%s enter\n", __func__); |
| 350 | 316 | ||
| 351 | stat = SPORT_GET_STAT(up); | ||
| 352 | while(!(stat & TXHRE)) { | ||
| 353 | udelay(1); | ||
| 354 | stat = SPORT_GET_STAT(up); | ||
| 355 | } | ||
| 356 | /* Although the hold register is empty, last byte is still in shift | 317 | /* Although the hold register is empty, last byte is still in shift |
| 357 | * register and not sent out yet. If baud rate is lower than default, | 318 | * register and not sent out yet. So, put a dummy data into TX FIFO. |
| 358 | * delay should be longer. For example, if the baud rate is 9600, | 319 | * Then, sport tx stops when last byte is shift out and the dummy |
| 359 | * the delay must be at least 2ms by experience */ | 320 | * data is moved into the shift register. |
| 360 | udelay(500); | 321 | */ |
| 322 | SPORT_PUT_TX(up, 0xffff); | ||
| 323 | while (!(SPORT_GET_STAT(up) & TXHRE)) | ||
| 324 | cpu_relax(); | ||
| 361 | 325 | ||
| 362 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | 326 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); |
| 363 | SSYNC(); | 327 | SSYNC(); |
| @@ -370,6 +334,7 @@ static void sport_start_tx(struct uart_port *port) | |||
| 370 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 334 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
| 371 | 335 | ||
| 372 | pr_debug("%s enter\n", __func__); | 336 | pr_debug("%s enter\n", __func__); |
| 337 | |||
| 373 | /* Write data into SPORT FIFO before enable SPROT to transmit */ | 338 | /* Write data into SPORT FIFO before enable SPROT to transmit */ |
| 374 | sport_uart_tx_chars(up); | 339 | sport_uart_tx_chars(up); |
| 375 | 340 | ||
| @@ -403,37 +368,24 @@ static void sport_shutdown(struct uart_port *port) | |||
| 403 | { | 368 | { |
| 404 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 369 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
| 405 | 370 | ||
| 406 | pr_debug("%s enter\n", __func__); | 371 | dev_dbg(port->dev, "%s enter\n", __func__); |
| 407 | 372 | ||
| 408 | /* Disable sport */ | 373 | /* Disable sport */ |
| 409 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | 374 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); |
| 410 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); | 375 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); |
| 411 | SSYNC(); | 376 | SSYNC(); |
| 412 | 377 | ||
| 413 | if (port->line) { | 378 | free_irq(up->port.irq, up); |
| 414 | peripheral_free_list(bfin_uart_pin_req_sport1); | 379 | free_irq(up->port.irq+1, up); |
| 415 | } else { | ||
| 416 | peripheral_free_list(bfin_uart_pin_req_sport0); | ||
| 417 | } | ||
| 418 | |||
| 419 | free_irq(up->rx_irq, up); | ||
| 420 | free_irq(up->tx_irq, up); | ||
| 421 | free_irq(up->err_irq, up); | 380 | free_irq(up->err_irq, up); |
| 422 | } | 381 | } |
| 423 | 382 | ||
| 424 | static void sport_set_termios(struct uart_port *port, | ||
| 425 | struct ktermios *termios, struct ktermios *old) | ||
| 426 | { | ||
| 427 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); | ||
| 428 | uart_update_timeout(port, CS8 ,port->uartclk); | ||
| 429 | } | ||
| 430 | |||
| 431 | static const char *sport_type(struct uart_port *port) | 383 | static const char *sport_type(struct uart_port *port) |
| 432 | { | 384 | { |
| 433 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 385 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
| 434 | 386 | ||
| 435 | pr_debug("%s enter\n", __func__); | 387 | pr_debug("%s enter\n", __func__); |
| 436 | return up->name; | 388 | return up->port.type == PORT_BFIN_SPORT ? "BFIN-SPORT-UART" : NULL; |
| 437 | } | 389 | } |
| 438 | 390 | ||
| 439 | static void sport_release_port(struct uart_port *port) | 391 | static void sport_release_port(struct uart_port *port) |
| @@ -461,6 +413,110 @@ static int sport_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
| 461 | return 0; | 413 | return 0; |
| 462 | } | 414 | } |
| 463 | 415 | ||
| 416 | static void sport_set_termios(struct uart_port *port, | ||
| 417 | struct ktermios *termios, struct ktermios *old) | ||
| 418 | { | ||
| 419 | struct sport_uart_port *up = (struct sport_uart_port *)port; | ||
| 420 | unsigned long flags; | ||
| 421 | int i; | ||
| 422 | |||
| 423 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); | ||
| 424 | |||
| 425 | switch (termios->c_cflag & CSIZE) { | ||
| 426 | case CS8: | ||
| 427 | up->csize = 8; | ||
| 428 | break; | ||
| 429 | case CS7: | ||
| 430 | up->csize = 7; | ||
| 431 | break; | ||
| 432 | case CS6: | ||
| 433 | up->csize = 6; | ||
| 434 | break; | ||
| 435 | case CS5: | ||
| 436 | up->csize = 5; | ||
| 437 | break; | ||
| 438 | default: | ||
| 439 | pr_warning("requested word length not supported\n"); | ||
| 440 | } | ||
| 441 | |||
| 442 | if (termios->c_cflag & CSTOPB) { | ||
| 443 | up->stopb = 1; | ||
| 444 | } | ||
| 445 | if (termios->c_cflag & PARENB) { | ||
| 446 | pr_warning("PAREN bits is not supported yet\n"); | ||
| 447 | /* up->parib = 1; */ | ||
| 448 | } | ||
| 449 | |||
| 450 | port->read_status_mask = OE; | ||
| 451 | if (termios->c_iflag & INPCK) | ||
| 452 | port->read_status_mask |= (FE | PE); | ||
| 453 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
| 454 | port->read_status_mask |= BI; | ||
| 455 | |||
| 456 | /* | ||
| 457 | * Characters to ignore | ||
| 458 | */ | ||
| 459 | port->ignore_status_mask = 0; | ||
| 460 | if (termios->c_iflag & IGNPAR) | ||
| 461 | port->ignore_status_mask |= FE | PE; | ||
| 462 | if (termios->c_iflag & IGNBRK) { | ||
| 463 | port->ignore_status_mask |= BI; | ||
| 464 | /* | ||
| 465 | * If we're ignoring parity and break indicators, | ||
| 466 | * ignore overruns too (for real raw support). | ||
| 467 | */ | ||
| 468 | if (termios->c_iflag & IGNPAR) | ||
| 469 | port->ignore_status_mask |= OE; | ||
| 470 | } | ||
| 471 | |||
| 472 | /* RX extract mask */ | ||
| 473 | up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8); | ||
| 474 | /* TX masks, 8 bit data and 1 bit stop for example: | ||
| 475 | * mask1 = b#0111111110 | ||
| 476 | * mask2 = b#1000000000 | ||
| 477 | */ | ||
| 478 | for (i = 0, up->txmask1 = 0; i < up->csize; i++) | ||
| 479 | up->txmask1 |= (1<<i); | ||
| 480 | up->txmask2 = (1<<i); | ||
| 481 | if (up->stopb) { | ||
| 482 | ++i; | ||
| 483 | up->txmask2 |= (1<<i); | ||
| 484 | } | ||
| 485 | up->txmask1 <<= 1; | ||
| 486 | up->txmask2 <<= 1; | ||
| 487 | /* uart baud rate */ | ||
| 488 | port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16); | ||
| 489 | |||
| 490 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 491 | |||
| 492 | /* Disable UART */ | ||
| 493 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); | ||
| 494 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); | ||
| 495 | |||
| 496 | sport_uart_setup(up, up->csize + up->stopb, port->uartclk); | ||
| 497 | |||
| 498 | /* driver TX line high after config, one dummy data is | ||
| 499 | * necessary to stop sport after shift one byte | ||
| 500 | */ | ||
| 501 | SPORT_PUT_TX(up, 0xffff); | ||
| 502 | SPORT_PUT_TX(up, 0xffff); | ||
| 503 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | ||
| 504 | SSYNC(); | ||
| 505 | while (!(SPORT_GET_STAT(up) & TXHRE)) | ||
| 506 | cpu_relax(); | ||
| 507 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); | ||
| 508 | SSYNC(); | ||
| 509 | |||
| 510 | /* Port speed changed, update the per-port timeout. */ | ||
| 511 | uart_update_timeout(port, termios->c_cflag, port->uartclk); | ||
| 512 | |||
| 513 | /* Enable sport rx */ | ||
| 514 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN); | ||
| 515 | SSYNC(); | ||
| 516 | |||
| 517 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 518 | } | ||
| 519 | |||
| 464 | struct uart_ops sport_uart_ops = { | 520 | struct uart_ops sport_uart_ops = { |
| 465 | .tx_empty = sport_tx_empty, | 521 | .tx_empty = sport_tx_empty, |
| 466 | .set_mctrl = sport_set_mctrl, | 522 | .set_mctrl = sport_set_mctrl, |
| @@ -480,138 +536,319 @@ struct uart_ops sport_uart_ops = { | |||
| 480 | .verify_port = sport_verify_port, | 536 | .verify_port = sport_verify_port, |
| 481 | }; | 537 | }; |
| 482 | 538 | ||
| 483 | static struct sport_uart_port sport_uart_ports[] = { | 539 | #define BFIN_SPORT_UART_MAX_PORTS 4 |
| 484 | { /* SPORT 0 */ | 540 | |
| 485 | .name = "SPORT0", | 541 | static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS]; |
| 486 | .tx_irq = IRQ_SPORT0_TX, | 542 | |
| 487 | .rx_irq = IRQ_SPORT0_RX, | 543 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE |
| 488 | .err_irq= IRQ_SPORT0_ERROR, | 544 | static int __init |
| 489 | .port = { | 545 | sport_uart_console_setup(struct console *co, char *options) |
| 490 | .type = PORT_BFIN_SPORT, | 546 | { |
| 491 | .iotype = UPIO_MEM, | 547 | struct sport_uart_port *up; |
| 492 | .membase = (void __iomem *)SPORT0_TCR1, | 548 | int baud = 57600; |
| 493 | .mapbase = SPORT0_TCR1, | 549 | int bits = 8; |
| 494 | .irq = IRQ_SPORT0_RX, | 550 | int parity = 'n'; |
| 495 | .uartclk = CONFIG_SPORT_BAUD_RATE, | 551 | int flow = 'n'; |
| 496 | .fifosize = 8, | 552 | |
| 497 | .ops = &sport_uart_ops, | 553 | /* Check whether an invalid uart number has been specified */ |
| 498 | .line = 0, | 554 | if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS) |
| 499 | }, | 555 | return -ENODEV; |
| 500 | }, { /* SPORT 1 */ | 556 | |
| 501 | .name = "SPORT1", | 557 | up = bfin_sport_uart_ports[co->index]; |
| 502 | .tx_irq = IRQ_SPORT1_TX, | 558 | if (!up) |
| 503 | .rx_irq = IRQ_SPORT1_RX, | 559 | return -ENODEV; |
| 504 | .err_irq= IRQ_SPORT1_ERROR, | 560 | |
| 505 | .port = { | 561 | if (options) |
| 506 | .type = PORT_BFIN_SPORT, | 562 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
| 507 | .iotype = UPIO_MEM, | 563 | |
| 508 | .membase = (void __iomem *)SPORT1_TCR1, | 564 | return uart_set_options(&up->port, co, baud, parity, bits, flow); |
| 509 | .mapbase = SPORT1_TCR1, | 565 | } |
| 510 | .irq = IRQ_SPORT1_RX, | 566 | |
| 511 | .uartclk = CONFIG_SPORT_BAUD_RATE, | 567 | static void sport_uart_console_putchar(struct uart_port *port, int ch) |
| 512 | .fifosize = 8, | 568 | { |
| 513 | .ops = &sport_uart_ops, | 569 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
| 514 | .line = 1, | 570 | |
| 515 | }, | 571 | while (SPORT_GET_STAT(up) & TXF) |
| 572 | barrier(); | ||
| 573 | |||
| 574 | tx_one_byte(up, ch); | ||
| 575 | } | ||
| 576 | |||
| 577 | /* | ||
| 578 | * Interrupts are disabled on entering | ||
| 579 | */ | ||
| 580 | static void | ||
| 581 | sport_uart_console_write(struct console *co, const char *s, unsigned int count) | ||
| 582 | { | ||
| 583 | struct sport_uart_port *up = bfin_sport_uart_ports[co->index]; | ||
| 584 | unsigned long flags; | ||
| 585 | |||
| 586 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 587 | |||
| 588 | if (SPORT_GET_TCR1(up) & TSPEN) | ||
| 589 | uart_console_write(&up->port, s, count, sport_uart_console_putchar); | ||
| 590 | else { | ||
| 591 | /* dummy data to start sport */ | ||
| 592 | while (SPORT_GET_STAT(up) & TXF) | ||
| 593 | barrier(); | ||
| 594 | SPORT_PUT_TX(up, 0xffff); | ||
| 595 | /* Enable transmit, then an interrupt will generated */ | ||
| 596 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | ||
| 597 | SSYNC(); | ||
| 598 | |||
| 599 | uart_console_write(&up->port, s, count, sport_uart_console_putchar); | ||
| 600 | |||
| 601 | /* Although the hold register is empty, last byte is still in shift | ||
| 602 | * register and not sent out yet. So, put a dummy data into TX FIFO. | ||
| 603 | * Then, sport tx stops when last byte is shift out and the dummy | ||
| 604 | * data is moved into the shift register. | ||
| 605 | */ | ||
| 606 | while (SPORT_GET_STAT(up) & TXF) | ||
| 607 | barrier(); | ||
| 608 | SPORT_PUT_TX(up, 0xffff); | ||
| 609 | while (!(SPORT_GET_STAT(up) & TXHRE)) | ||
| 610 | barrier(); | ||
| 611 | |||
| 612 | /* Stop sport tx transfer */ | ||
| 613 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | ||
| 614 | SSYNC(); | ||
| 516 | } | 615 | } |
| 616 | |||
| 617 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 618 | } | ||
| 619 | |||
| 620 | static struct uart_driver sport_uart_reg; | ||
| 621 | |||
| 622 | static struct console sport_uart_console = { | ||
| 623 | .name = DEVICE_NAME, | ||
| 624 | .write = sport_uart_console_write, | ||
| 625 | .device = uart_console_device, | ||
| 626 | .setup = sport_uart_console_setup, | ||
| 627 | .flags = CON_PRINTBUFFER, | ||
| 628 | .index = -1, | ||
| 629 | .data = &sport_uart_reg, | ||
| 517 | }; | 630 | }; |
| 518 | 631 | ||
| 632 | #define SPORT_UART_CONSOLE (&sport_uart_console) | ||
| 633 | #else | ||
| 634 | #define SPORT_UART_CONSOLE NULL | ||
| 635 | #endif /* CONFIG_SERIAL_BFIN_SPORT_CONSOLE */ | ||
| 636 | |||
| 637 | |||
| 519 | static struct uart_driver sport_uart_reg = { | 638 | static struct uart_driver sport_uart_reg = { |
| 520 | .owner = THIS_MODULE, | 639 | .owner = THIS_MODULE, |
| 521 | .driver_name = "SPORT-UART", | 640 | .driver_name = DRV_NAME, |
| 522 | .dev_name = "ttySS", | 641 | .dev_name = DEVICE_NAME, |
| 523 | .major = 204, | 642 | .major = 204, |
| 524 | .minor = 84, | 643 | .minor = 84, |
| 525 | .nr = ARRAY_SIZE(sport_uart_ports), | 644 | .nr = BFIN_SPORT_UART_MAX_PORTS, |
| 526 | .cons = NULL, | 645 | .cons = SPORT_UART_CONSOLE, |
| 527 | }; | 646 | }; |
| 528 | 647 | ||
| 529 | static int sport_uart_suspend(struct platform_device *dev, pm_message_t state) | 648 | #ifdef CONFIG_PM |
| 649 | static int sport_uart_suspend(struct device *dev) | ||
| 530 | { | 650 | { |
| 531 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 651 | struct sport_uart_port *sport = dev_get_drvdata(dev); |
| 532 | 652 | ||
| 533 | pr_debug("%s enter\n", __func__); | 653 | dev_dbg(dev, "%s enter\n", __func__); |
| 534 | if (sport) | 654 | if (sport) |
| 535 | uart_suspend_port(&sport_uart_reg, &sport->port); | 655 | uart_suspend_port(&sport_uart_reg, &sport->port); |
| 536 | 656 | ||
| 537 | return 0; | 657 | return 0; |
| 538 | } | 658 | } |
| 539 | 659 | ||
| 540 | static int sport_uart_resume(struct platform_device *dev) | 660 | static int sport_uart_resume(struct device *dev) |
| 541 | { | 661 | { |
| 542 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 662 | struct sport_uart_port *sport = dev_get_drvdata(dev); |
| 543 | 663 | ||
| 544 | pr_debug("%s enter\n", __func__); | 664 | dev_dbg(dev, "%s enter\n", __func__); |
| 545 | if (sport) | 665 | if (sport) |
| 546 | uart_resume_port(&sport_uart_reg, &sport->port); | 666 | uart_resume_port(&sport_uart_reg, &sport->port); |
| 547 | 667 | ||
| 548 | return 0; | 668 | return 0; |
| 549 | } | 669 | } |
| 550 | 670 | ||
| 551 | static int sport_uart_probe(struct platform_device *dev) | 671 | static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = { |
| 672 | .suspend = sport_uart_suspend, | ||
| 673 | .resume = sport_uart_resume, | ||
| 674 | }; | ||
| 675 | #endif | ||
| 676 | |||
| 677 | static int __devinit sport_uart_probe(struct platform_device *pdev) | ||
| 552 | { | 678 | { |
| 553 | pr_debug("%s enter\n", __func__); | 679 | struct resource *res; |
| 554 | sport_uart_ports[dev->id].port.dev = &dev->dev; | 680 | struct sport_uart_port *sport; |
| 555 | uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port); | 681 | int ret = 0; |
| 556 | platform_set_drvdata(dev, &sport_uart_ports[dev->id]); | ||
| 557 | 682 | ||
| 558 | return 0; | 683 | dev_dbg(&pdev->dev, "%s enter\n", __func__); |
| 684 | |||
| 685 | if (pdev->id < 0 || pdev->id >= BFIN_SPORT_UART_MAX_PORTS) { | ||
| 686 | dev_err(&pdev->dev, "Wrong sport uart platform device id.\n"); | ||
| 687 | return -ENOENT; | ||
| 688 | } | ||
| 689 | |||
| 690 | if (bfin_sport_uart_ports[pdev->id] == NULL) { | ||
| 691 | bfin_sport_uart_ports[pdev->id] = | ||
| 692 | kmalloc(sizeof(struct sport_uart_port), GFP_KERNEL); | ||
| 693 | sport = bfin_sport_uart_ports[pdev->id]; | ||
| 694 | if (!sport) { | ||
| 695 | dev_err(&pdev->dev, | ||
| 696 | "Fail to kmalloc sport_uart_port\n"); | ||
| 697 | return -ENOMEM; | ||
| 698 | } | ||
| 699 | |||
| 700 | ret = peripheral_request_list( | ||
| 701 | (unsigned short *)pdev->dev.platform_data, DRV_NAME); | ||
| 702 | if (ret) { | ||
| 703 | dev_err(&pdev->dev, | ||
| 704 | "Fail to request SPORT peripherals\n"); | ||
| 705 | goto out_error_free_mem; | ||
| 706 | } | ||
| 707 | |||
| 708 | spin_lock_init(&sport->port.lock); | ||
| 709 | sport->port.fifosize = SPORT_TX_FIFO_SIZE, | ||
| 710 | sport->port.ops = &sport_uart_ops; | ||
| 711 | sport->port.line = pdev->id; | ||
| 712 | sport->port.iotype = UPIO_MEM; | ||
| 713 | sport->port.flags = UPF_BOOT_AUTOCONF; | ||
| 714 | |||
| 715 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 716 | if (res == NULL) { | ||
| 717 | dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); | ||
| 718 | ret = -ENOENT; | ||
| 719 | goto out_error_free_peripherals; | ||
| 720 | } | ||
| 721 | |||
| 722 | sport->port.membase = ioremap(res->start, | ||
| 723 | res->end - res->start); | ||
| 724 | if (!sport->port.membase) { | ||
| 725 | dev_err(&pdev->dev, "Cannot map sport IO\n"); | ||
| 726 | ret = -ENXIO; | ||
| 727 | goto out_error_free_peripherals; | ||
| 728 | } | ||
| 729 | |||
| 730 | sport->port.irq = platform_get_irq(pdev, 0); | ||
| 731 | if (sport->port.irq < 0) { | ||
| 732 | dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n"); | ||
| 733 | ret = -ENOENT; | ||
| 734 | goto out_error_unmap; | ||
| 735 | } | ||
| 736 | |||
| 737 | sport->err_irq = platform_get_irq(pdev, 1); | ||
| 738 | if (sport->err_irq < 0) { | ||
| 739 | dev_err(&pdev->dev, "No sport status IRQ specified\n"); | ||
| 740 | ret = -ENOENT; | ||
| 741 | goto out_error_unmap; | ||
| 742 | } | ||
| 743 | } | ||
| 744 | |||
| 745 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | ||
| 746 | if (!is_early_platform_device(pdev)) { | ||
| 747 | #endif | ||
| 748 | sport = bfin_sport_uart_ports[pdev->id]; | ||
| 749 | sport->port.dev = &pdev->dev; | ||
| 750 | dev_set_drvdata(&pdev->dev, sport); | ||
| 751 | ret = uart_add_one_port(&sport_uart_reg, &sport->port); | ||
| 752 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | ||
| 753 | } | ||
| 754 | #endif | ||
| 755 | if (!ret) | ||
| 756 | return 0; | ||
| 757 | |||
| 758 | if (sport) { | ||
| 759 | out_error_unmap: | ||
| 760 | iounmap(sport->port.membase); | ||
| 761 | out_error_free_peripherals: | ||
| 762 | peripheral_free_list( | ||
| 763 | (unsigned short *)pdev->dev.platform_data); | ||
| 764 | out_error_free_mem: | ||
| 765 | kfree(sport); | ||
| 766 | bfin_sport_uart_ports[pdev->id] = NULL; | ||
| 767 | } | ||
| 768 | |||
| 769 | return ret; | ||
| 559 | } | 770 | } |
| 560 | 771 | ||
| 561 | static int sport_uart_remove(struct platform_device *dev) | 772 | static int __devexit sport_uart_remove(struct platform_device *pdev) |
| 562 | { | 773 | { |
| 563 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 774 | struct sport_uart_port *sport = platform_get_drvdata(pdev); |
| 564 | 775 | ||
| 565 | pr_debug("%s enter\n", __func__); | 776 | dev_dbg(&pdev->dev, "%s enter\n", __func__); |
| 566 | platform_set_drvdata(dev, NULL); | 777 | dev_set_drvdata(&pdev->dev, NULL); |
| 567 | 778 | ||
| 568 | if (sport) | 779 | if (sport) { |
| 569 | uart_remove_one_port(&sport_uart_reg, &sport->port); | 780 | uart_remove_one_port(&sport_uart_reg, &sport->port); |
| 781 | iounmap(sport->port.membase); | ||
| 782 | peripheral_free_list( | ||
| 783 | (unsigned short *)pdev->dev.platform_data); | ||
| 784 | kfree(sport); | ||
| 785 | bfin_sport_uart_ports[pdev->id] = NULL; | ||
| 786 | } | ||
| 570 | 787 | ||
| 571 | return 0; | 788 | return 0; |
| 572 | } | 789 | } |
| 573 | 790 | ||
| 574 | static struct platform_driver sport_uart_driver = { | 791 | static struct platform_driver sport_uart_driver = { |
| 575 | .probe = sport_uart_probe, | 792 | .probe = sport_uart_probe, |
| 576 | .remove = sport_uart_remove, | 793 | .remove = __devexit_p(sport_uart_remove), |
| 577 | .suspend = sport_uart_suspend, | ||
| 578 | .resume = sport_uart_resume, | ||
| 579 | .driver = { | 794 | .driver = { |
| 580 | .name = DRV_NAME, | 795 | .name = DRV_NAME, |
| 796 | #ifdef CONFIG_PM | ||
| 797 | .pm = &bfin_sport_uart_dev_pm_ops, | ||
| 798 | #endif | ||
| 581 | }, | 799 | }, |
| 582 | }; | 800 | }; |
| 583 | 801 | ||
| 802 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | ||
| 803 | static __initdata struct early_platform_driver early_sport_uart_driver = { | ||
| 804 | .class_str = DRV_NAME, | ||
| 805 | .pdrv = &sport_uart_driver, | ||
| 806 | .requested_id = EARLY_PLATFORM_ID_UNSET, | ||
| 807 | }; | ||
| 808 | |||
| 809 | static int __init sport_uart_rs_console_init(void) | ||
| 810 | { | ||
| 811 | early_platform_driver_register(&early_sport_uart_driver, DRV_NAME); | ||
| 812 | |||
| 813 | early_platform_driver_probe(DRV_NAME, BFIN_SPORT_UART_MAX_PORTS, 0); | ||
| 814 | |||
| 815 | register_console(&sport_uart_console); | ||
| 816 | |||
| 817 | return 0; | ||
| 818 | } | ||
| 819 | console_initcall(sport_uart_rs_console_init); | ||
| 820 | #endif | ||
| 821 | |||
| 584 | static int __init sport_uart_init(void) | 822 | static int __init sport_uart_init(void) |
| 585 | { | 823 | { |
| 586 | int ret; | 824 | int ret; |
| 587 | 825 | ||
| 588 | pr_debug("%s enter\n", __func__); | 826 | pr_info("Serial: Blackfin uart over sport driver\n"); |
| 827 | |||
| 589 | ret = uart_register_driver(&sport_uart_reg); | 828 | ret = uart_register_driver(&sport_uart_reg); |
| 590 | if (ret != 0) { | 829 | if (ret) { |
| 591 | printk(KERN_ERR "Failed to register %s:%d\n", | 830 | pr_err("failed to register %s:%d\n", |
| 592 | sport_uart_reg.driver_name, ret); | 831 | sport_uart_reg.driver_name, ret); |
| 593 | return ret; | 832 | return ret; |
| 594 | } | 833 | } |
| 595 | 834 | ||
| 596 | ret = platform_driver_register(&sport_uart_driver); | 835 | ret = platform_driver_register(&sport_uart_driver); |
| 597 | if (ret != 0) { | 836 | if (ret) { |
| 598 | printk(KERN_ERR "Failed to register sport uart driver:%d\n", ret); | 837 | pr_err("failed to register sport uart driver:%d\n", ret); |
| 599 | uart_unregister_driver(&sport_uart_reg); | 838 | uart_unregister_driver(&sport_uart_reg); |
| 600 | } | 839 | } |
| 601 | 840 | ||
| 602 | |||
| 603 | pr_debug("%s exit\n", __func__); | ||
| 604 | return ret; | 841 | return ret; |
| 605 | } | 842 | } |
| 843 | module_init(sport_uart_init); | ||
| 606 | 844 | ||
| 607 | static void __exit sport_uart_exit(void) | 845 | static void __exit sport_uart_exit(void) |
| 608 | { | 846 | { |
| 609 | pr_debug("%s enter\n", __func__); | ||
| 610 | platform_driver_unregister(&sport_uart_driver); | 847 | platform_driver_unregister(&sport_uart_driver); |
| 611 | uart_unregister_driver(&sport_uart_reg); | 848 | uart_unregister_driver(&sport_uart_reg); |
| 612 | } | 849 | } |
| 613 | |||
| 614 | module_init(sport_uart_init); | ||
| 615 | module_exit(sport_uart_exit); | 850 | module_exit(sport_uart_exit); |
| 616 | 851 | ||
| 852 | MODULE_AUTHOR("Sonic Zhang, Roy Huang"); | ||
| 853 | MODULE_DESCRIPTION("Blackfin serial over SPORT driver"); | ||
| 617 | MODULE_LICENSE("GPL"); | 854 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h index 671d41cc1a3f..abe03614e4df 100644 --- a/drivers/serial/bfin_sport_uart.h +++ b/drivers/serial/bfin_sport_uart.h | |||
| @@ -1,29 +1,23 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * File: linux/drivers/serial/bfin_sport_uart.h | 2 | * Blackfin On-Chip Sport Emulated UART Driver |
| 3 | * | 3 | * |
| 4 | * Based on: include/asm-blackfin/mach-533/bfin_serial_5xx.h | 4 | * Copyright 2006-2008 Analog Devices Inc. |
| 5 | * Author: Roy Huang <roy.huang>analog.com> | ||
| 6 | * | 5 | * |
| 7 | * Created: Nov 22, 2006 | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
| 8 | * Copyright: (C) Analog Device Inc. | ||
| 9 | * Description: this driver enable SPORTs on Blackfin emulate UART. | ||
| 10 | * | 7 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 8 | * Licensed under the GPL-2 or later. |
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, see the file COPYING, or write | ||
| 23 | * to the Free Software Foundation, Inc., | ||
| 24 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 25 | */ | 9 | */ |
| 26 | 10 | ||
| 11 | /* | ||
| 12 | * This driver and the hardware supported are in term of EE-191 of ADI. | ||
| 13 | * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf | ||
| 14 | * This application note describe how to implement a UART on a Sharc DSP, | ||
| 15 | * but this driver is implemented on Blackfin Processor. | ||
| 16 | * Transmit Frame Sync is not used by this driver to transfer data out. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef _BFIN_SPORT_UART_H | ||
| 20 | #define _BFIN_SPORT_UART_H | ||
| 27 | 21 | ||
| 28 | #define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */ | 22 | #define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */ |
| 29 | #define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */ | 23 | #define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */ |
| @@ -61,3 +55,7 @@ | |||
| 61 | #define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v) | 55 | #define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v) |
| 62 | #define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v) | 56 | #define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v) |
| 63 | #define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v) | 57 | #define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v) |
| 58 | |||
| 59 | #define SPORT_TX_FIFO_SIZE 8 | ||
| 60 | |||
| 61 | #endif /* _BFIN_SPORT_UART_H */ | ||
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 0028b6f89ce6..53a468227056 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c | |||
| @@ -751,7 +751,6 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) | |||
| 751 | trace(icom_port, "FID_STATUS", status); | 751 | trace(icom_port, "FID_STATUS", status); |
| 752 | count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength); | 752 | count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength); |
| 753 | 753 | ||
| 754 | count = tty_buffer_request_room(tty, count); | ||
| 755 | trace(icom_port, "RCV_COUNT", count); | 754 | trace(icom_port, "RCV_COUNT", count); |
| 756 | 755 | ||
| 757 | trace(icom_port, "REAL_COUNT", count); | 756 | trace(icom_port, "REAL_COUNT", count); |
| @@ -1654,4 +1653,6 @@ MODULE_DESCRIPTION("IBM iSeries Serial IOA driver"); | |||
| 1654 | MODULE_SUPPORTED_DEVICE | 1653 | MODULE_SUPPORTED_DEVICE |
| 1655 | ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters"); | 1654 | ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters"); |
| 1656 | MODULE_LICENSE("GPL"); | 1655 | MODULE_LICENSE("GPL"); |
| 1657 | 1656 | MODULE_FIRMWARE("icom_call_setup.bin"); | |
| 1657 | MODULE_FIRMWARE("icom_res_dce.bin"); | ||
| 1658 | MODULE_FIRMWARE("icom_asc.bin"); | ||
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 60d665a17a88..d00fcf8e6c70 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -1279,7 +1279,7 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
| 1279 | sport->use_irda = 1; | 1279 | sport->use_irda = 1; |
| 1280 | #endif | 1280 | #endif |
| 1281 | 1281 | ||
| 1282 | if (pdata->init) { | 1282 | if (pdata && pdata->init) { |
| 1283 | ret = pdata->init(pdev); | 1283 | ret = pdata->init(pdev); |
| 1284 | if (ret) | 1284 | if (ret) |
| 1285 | goto clkput; | 1285 | goto clkput; |
| @@ -1292,7 +1292,7 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
| 1292 | 1292 | ||
| 1293 | return 0; | 1293 | return 0; |
| 1294 | deinit: | 1294 | deinit: |
| 1295 | if (pdata->exit) | 1295 | if (pdata && pdata->exit) |
| 1296 | pdata->exit(pdev); | 1296 | pdata->exit(pdev); |
| 1297 | clkput: | 1297 | clkput: |
| 1298 | clk_put(sport->clk); | 1298 | clk_put(sport->clk); |
| @@ -1321,7 +1321,7 @@ static int serial_imx_remove(struct platform_device *pdev) | |||
| 1321 | 1321 | ||
| 1322 | clk_disable(sport->clk); | 1322 | clk_disable(sport->clk); |
| 1323 | 1323 | ||
| 1324 | if (pdata->exit) | 1324 | if (pdata && pdata->exit) |
| 1325 | pdata->exit(pdev); | 1325 | pdata->exit(pdev); |
| 1326 | 1326 | ||
| 1327 | iounmap(sport->port.membase); | 1327 | iounmap(sport->port.membase); |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 85dc0410ac1a..23ba6b40b3ac 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
| @@ -1411,8 +1411,7 @@ static int receive_chars(struct uart_port *the_port) | |||
| 1411 | read_count = do_read(the_port, ch, MAX_CHARS); | 1411 | read_count = do_read(the_port, ch, MAX_CHARS); |
| 1412 | if (read_count > 0) { | 1412 | if (read_count > 0) { |
| 1413 | flip = 1; | 1413 | flip = 1; |
| 1414 | read_room = tty_buffer_request_room(tty, read_count); | 1414 | read_room = tty_insert_flip_string(tty, ch, read_count); |
| 1415 | tty_insert_flip_string(tty, ch, read_room); | ||
| 1416 | the_port->icount.rx += read_count; | 1415 | the_port->icount.rx += read_count; |
| 1417 | } | 1416 | } |
| 1418 | spin_unlock_irqrestore(&the_port->lock, pflags); | 1417 | spin_unlock_irqrestore(&the_port->lock, pflags); |
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 108c3e0471fd..12cb5e446a4f 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
| @@ -179,6 +179,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
| 179 | 179 | ||
| 180 | return 0; | 180 | return 0; |
| 181 | out_free_irq: | 181 | out_free_irq: |
| 182 | jsm_remove_uart_port(brd); | ||
| 182 | free_irq(brd->irq, brd); | 183 | free_irq(brd->irq, brd); |
| 183 | out_iounmap: | 184 | out_iounmap: |
| 184 | iounmap(brd->re_map_membase); | 185 | iounmap(brd->re_map_membase); |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index cd95e215550d..5673ca9dfdc8 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
| @@ -432,7 +432,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) | |||
| 432 | 432 | ||
| 433 | int jsm_uart_port_init(struct jsm_board *brd) | 433 | int jsm_uart_port_init(struct jsm_board *brd) |
| 434 | { | 434 | { |
| 435 | int i; | 435 | int i, rc; |
| 436 | unsigned int line; | 436 | unsigned int line; |
| 437 | struct jsm_channel *ch; | 437 | struct jsm_channel *ch; |
| 438 | 438 | ||
| @@ -467,8 +467,11 @@ int jsm_uart_port_init(struct jsm_board *brd) | |||
| 467 | } else | 467 | } else |
| 468 | set_bit(line, linemap); | 468 | set_bit(line, linemap); |
| 469 | brd->channels[i]->uart_port.line = line; | 469 | brd->channels[i]->uart_port.line = line; |
| 470 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 470 | rc = uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port); |
| 471 | printk(KERN_INFO "jsm: add device failed\n"); | 471 | if (rc){ |
| 472 | printk(KERN_INFO "jsm: Port %d failed. Aborting...\n", i); | ||
| 473 | return rc; | ||
| 474 | } | ||
| 472 | else | 475 | else |
| 473 | printk(KERN_INFO "jsm: Port %d added\n", i); | 476 | printk(KERN_INFO "jsm: Port %d added\n", i); |
| 474 | } | 477 | } |
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c index b05c5aa02cb4..ecdc0facf7ee 100644 --- a/drivers/serial/msm_serial.c +++ b/drivers/serial/msm_serial.c | |||
| @@ -691,6 +691,7 @@ static int __init msm_serial_probe(struct platform_device *pdev) | |||
| 691 | struct msm_port *msm_port; | 691 | struct msm_port *msm_port; |
| 692 | struct resource *resource; | 692 | struct resource *resource; |
| 693 | struct uart_port *port; | 693 | struct uart_port *port; |
| 694 | int irq; | ||
| 694 | 695 | ||
| 695 | if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) | 696 | if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) |
| 696 | return -ENXIO; | 697 | return -ENXIO; |
| @@ -711,9 +712,10 @@ static int __init msm_serial_probe(struct platform_device *pdev) | |||
| 711 | return -ENXIO; | 712 | return -ENXIO; |
| 712 | port->mapbase = resource->start; | 713 | port->mapbase = resource->start; |
| 713 | 714 | ||
| 714 | port->irq = platform_get_irq(pdev, 0); | 715 | irq = platform_get_irq(pdev, 0); |
| 715 | if (unlikely(port->irq < 0)) | 716 | if (unlikely(irq < 0)) |
| 716 | return -ENXIO; | 717 | return -ENXIO; |
| 718 | port->irq = irq; | ||
| 717 | 719 | ||
| 718 | platform_set_drvdata(pdev, port); | 720 | platform_set_drvdata(pdev, port); |
| 719 | 721 | ||
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c index 34b31da01d09..7bf10264a6ac 100644 --- a/drivers/serial/timbuart.c +++ b/drivers/serial/timbuart.c | |||
| @@ -421,7 +421,7 @@ static struct uart_driver timbuart_driver = { | |||
| 421 | 421 | ||
| 422 | static int timbuart_probe(struct platform_device *dev) | 422 | static int timbuart_probe(struct platform_device *dev) |
| 423 | { | 423 | { |
| 424 | int err; | 424 | int err, irq; |
| 425 | struct timbuart_port *uart; | 425 | struct timbuart_port *uart; |
| 426 | struct resource *iomem; | 426 | struct resource *iomem; |
| 427 | 427 | ||
| @@ -453,11 +453,12 @@ static int timbuart_probe(struct platform_device *dev) | |||
| 453 | uart->port.mapbase = iomem->start; | 453 | uart->port.mapbase = iomem->start; |
| 454 | uart->port.membase = NULL; | 454 | uart->port.membase = NULL; |
| 455 | 455 | ||
| 456 | uart->port.irq = platform_get_irq(dev, 0); | 456 | irq = platform_get_irq(dev, 0); |
| 457 | if (uart->port.irq < 0) { | 457 | if (irq < 0) { |
| 458 | err = -EINVAL; | 458 | err = -EINVAL; |
| 459 | goto err_register; | 459 | goto err_register; |
| 460 | } | 460 | } |
| 461 | uart->port.irq = irq; | ||
| 461 | 462 | ||
| 462 | tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); | 463 | tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); |
| 463 | 464 | ||
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 1296a097f5c3..84f08e968e0b 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
| @@ -789,6 +789,13 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) | |||
| 789 | return 1; | 789 | return 1; |
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | #ifdef KEYSPAN | ||
| 793 | MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); | ||
| 794 | #endif | ||
| 795 | #ifdef XIRCOM | ||
| 796 | MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); | ||
| 797 | #endif | ||
| 798 | |||
| 792 | static int keyspan_pda_startup(struct usb_serial *serial) | 799 | static int keyspan_pda_startup(struct usb_serial *serial) |
| 793 | { | 800 | { |
| 794 | 801 | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c0e207c0c45a..9f688d243b86 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2332,6 +2332,8 @@ | |||
| 2332 | #define PCI_VENDOR_ID_KORENIX 0x1982 | 2332 | #define PCI_VENDOR_ID_KORENIX 0x1982 |
| 2333 | #define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 | 2333 | #define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 |
| 2334 | #define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff | 2334 | #define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff |
| 2335 | #define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700 | ||
| 2336 | #define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff | ||
| 2335 | 2337 | ||
| 2336 | #define PCI_VENDOR_ID_QMI 0x1a32 | 2338 | #define PCI_VENDOR_ID_QMI 0x1a32 |
| 2337 | 2339 | ||
| @@ -2696,6 +2698,7 @@ | |||
| 2696 | #define PCI_DEVICE_ID_NETMOS_9835 0x9835 | 2698 | #define PCI_DEVICE_ID_NETMOS_9835 0x9835 |
| 2697 | #define PCI_DEVICE_ID_NETMOS_9845 0x9845 | 2699 | #define PCI_DEVICE_ID_NETMOS_9845 0x9845 |
| 2698 | #define PCI_DEVICE_ID_NETMOS_9855 0x9855 | 2700 | #define PCI_DEVICE_ID_NETMOS_9855 0x9855 |
| 2701 | #define PCI_DEVICE_ID_NETMOS_9865 0x9865 | ||
| 2699 | #define PCI_DEVICE_ID_NETMOS_9901 0x9901 | 2702 | #define PCI_DEVICE_ID_NETMOS_9901 0x9901 |
| 2700 | 2703 | ||
| 2701 | #define PCI_VENDOR_ID_3COM_2 0xa727 | 2704 | #define PCI_VENDOR_ID_3COM_2 0xa727 |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 6abfcf5b5887..d96e5882f129 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -68,6 +68,16 @@ struct tty_buffer { | |||
| 68 | unsigned long data[0]; | 68 | unsigned long data[0]; |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | /* | ||
| 72 | * We default to dicing tty buffer allocations to this many characters | ||
| 73 | * in order to avoid multiple page allocations. We assume tty_buffer itself | ||
| 74 | * is under 256 bytes. See tty_buffer_find for the allocation logic this | ||
| 75 | * must match | ||
| 76 | */ | ||
| 77 | |||
| 78 | #define TTY_BUFFER_PAGE ((PAGE_SIZE - 256) / 2) | ||
| 79 | |||
| 80 | |||
| 71 | struct tty_bufhead { | 81 | struct tty_bufhead { |
| 72 | struct delayed_work work; | 82 | struct delayed_work work; |
| 73 | spinlock_t lock; | 83 | spinlock_t lock; |
diff --git a/include/linux/vt.h b/include/linux/vt.h index d5dd0bc408fd..778b7b2a47d4 100644 --- a/include/linux/vt.h +++ b/include/linux/vt.h | |||
| @@ -27,7 +27,7 @@ struct vt_mode { | |||
| 27 | #define VT_SETMODE 0x5602 /* set mode of active vt */ | 27 | #define VT_SETMODE 0x5602 /* set mode of active vt */ |
| 28 | #define VT_AUTO 0x00 /* auto vt switching */ | 28 | #define VT_AUTO 0x00 /* auto vt switching */ |
| 29 | #define VT_PROCESS 0x01 /* process controls switching */ | 29 | #define VT_PROCESS 0x01 /* process controls switching */ |
| 30 | #define VT_ACKACQ 0x02 /* acknowledge switch */ | 30 | #define VT_PROCESS_AUTO 0x02 /* process is notified of switching */ |
| 31 | 31 | ||
| 32 | struct vt_stat { | 32 | struct vt_stat { |
| 33 | unsigned short v_active; /* active vt */ | 33 | unsigned short v_active; /* active vt */ |
| @@ -38,6 +38,7 @@ struct vt_stat { | |||
| 38 | #define VT_SENDSIG 0x5604 /* signal to send to bitmask of vts */ | 38 | #define VT_SENDSIG 0x5604 /* signal to send to bitmask of vts */ |
| 39 | 39 | ||
| 40 | #define VT_RELDISP 0x5605 /* release display */ | 40 | #define VT_RELDISP 0x5605 /* release display */ |
| 41 | #define VT_ACKACQ 0x02 /* acknowledge switch */ | ||
| 41 | 42 | ||
| 42 | #define VT_ACTIVATE 0x5606 /* make vt active */ | 43 | #define VT_ACTIVATE 0x5606 /* make vt active */ |
| 43 | #define VT_WAITACTIVE 0x5607 /* wait for vt active */ | 44 | #define VT_WAITACTIVE 0x5607 /* wait for vt active */ |
