diff options
Diffstat (limited to 'drivers/tty')
26 files changed, 954 insertions, 264 deletions
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 6b78399bc7c9..58ad1c05b7f8 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ | 1 | obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ |
2 | tty_buffer.o tty_port.o tty_mutex.o | 2 | tty_buffer.o tty_port.o tty_mutex.o tty_ldsem.o |
3 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 3 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
4 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 4 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
5 | obj-$(CONFIG_AUDIT) += tty_audit.o | 5 | obj-$(CONFIG_AUDIT) += tty_audit.o |
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index b6f7d52f7c35..9d47f50c2755 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c | |||
@@ -1328,7 +1328,7 @@ out_error: | |||
1328 | */ | 1328 | */ |
1329 | static int __init hvc_iucv_config(char *val) | 1329 | static int __init hvc_iucv_config(char *val) |
1330 | { | 1330 | { |
1331 | return strict_strtoul(val, 10, &hvc_iucv_devices); | 1331 | return kstrtoul(val, 10, &hvc_iucv_devices); |
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | 1334 | ||
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 6c7fe90ad72d..cdcdb0ea061a 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -647,8 +647,7 @@ static void process_echoes(struct tty_struct *tty) | |||
647 | if (no_space_left) | 647 | if (no_space_left) |
648 | break; | 648 | break; |
649 | } else { | 649 | } else { |
650 | if (O_OPOST(tty) && | 650 | if (O_OPOST(tty)) { |
651 | !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { | ||
652 | int retval = do_output_char(c, tty, space); | 651 | int retval = do_output_char(c, tty, space); |
653 | if (retval < 0) | 652 | if (retval < 0) |
654 | break; | 653 | break; |
@@ -1516,12 +1515,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1516 | wake_up_interruptible(&tty->read_wait); | 1515 | wake_up_interruptible(&tty->read_wait); |
1517 | 1516 | ||
1518 | ldata->icanon = (L_ICANON(tty) != 0); | 1517 | ldata->icanon = (L_ICANON(tty) != 0); |
1519 | if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { | 1518 | |
1520 | ldata->raw = 1; | ||
1521 | ldata->real_raw = 1; | ||
1522 | n_tty_set_room(tty); | ||
1523 | return; | ||
1524 | } | ||
1525 | if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || | 1519 | if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || |
1526 | I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || | 1520 | I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || |
1527 | I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || | 1521 | I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || |
@@ -2045,7 +2039,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | |||
2045 | retval = -EIO; | 2039 | retval = -EIO; |
2046 | break; | 2040 | break; |
2047 | } | 2041 | } |
2048 | if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { | 2042 | if (O_OPOST(tty)) { |
2049 | while (nr > 0) { | 2043 | while (nr > 0) { |
2050 | ssize_t num = process_output_block(tty, b, nr); | 2044 | ssize_t num = process_output_block(tty, b, nr); |
2051 | if (num < 0) { | 2045 | if (num < 0) { |
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 80fe91e64a52..a1ba94d64885 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig | |||
@@ -12,9 +12,8 @@ config SERIAL_8250 | |||
12 | here are those that are setting up dedicated Ethernet WWW/FTP | 12 | here are those that are setting up dedicated Ethernet WWW/FTP |
13 | servers, or users that have one of the various bus mice instead of a | 13 | servers, or users that have one of the various bus mice instead of a |
14 | serial mouse and don't intend to use their machine's standard serial | 14 | serial mouse and don't intend to use their machine's standard serial |
15 | port for anything. (Note that the Cyclades and Stallion multi | 15 | port for anything. (Note that the Cyclades multi serial port driver |
16 | serial port drivers do not need this driver built in for them to | 16 | does not need this driver built in for it to work.) |
17 | work.) | ||
18 | 17 | ||
19 | To compile this driver as a module, choose M here: the | 18 | To compile this driver as a module, choose M here: the |
20 | module will be called 8250. | 19 | module will be called 8250. |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 7e7006fd404e..95e66acca165 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -551,7 +551,7 @@ config BFIN_UART3_CTSRTS | |||
551 | Enable hardware flow control in the driver. | 551 | Enable hardware flow control in the driver. |
552 | 552 | ||
553 | config SERIAL_IMX | 553 | config SERIAL_IMX |
554 | bool "IMX serial port support" | 554 | tristate "IMX serial port support" |
555 | depends on ARCH_MXC | 555 | depends on ARCH_MXC |
556 | select SERIAL_CORE | 556 | select SERIAL_CORE |
557 | select RATIONAL | 557 | select RATIONAL |
@@ -561,22 +561,21 @@ config SERIAL_IMX | |||
561 | 561 | ||
562 | config SERIAL_IMX_CONSOLE | 562 | config SERIAL_IMX_CONSOLE |
563 | bool "Console on IMX serial port" | 563 | bool "Console on IMX serial port" |
564 | depends on SERIAL_IMX | 564 | depends on SERIAL_IMX=y |
565 | select SERIAL_CORE_CONSOLE | 565 | select SERIAL_CORE_CONSOLE |
566 | help | 566 | help |
567 | If you have enabled the serial port on the Motorola IMX | 567 | If you have enabled the serial port on the Freescale IMX |
568 | CPU you can make it the console by answering Y to this option. | 568 | CPU you can make it the console by answering Y to this option. |
569 | 569 | ||
570 | Even if you say Y here, the currently visible virtual console | 570 | Even if you say Y here, the currently visible virtual console |
571 | (/dev/tty0) will still be used as the system console by default, but | 571 | (/dev/tty0) will still be used as the system console by default, but |
572 | you can alter that using a kernel command line option such as | 572 | you can alter that using a kernel command line option such as |
573 | "console=ttySA0". (Try "man bootparam" or see the documentation of | 573 | "console=ttymxc0". (Try "man bootparam" or see the documentation of |
574 | your boot loader (lilo or loadlin) about how to pass options to the | 574 | your bootloader about how to pass options to the kernel at boot time.) |
575 | kernel at boot time.) | ||
576 | 575 | ||
577 | config SERIAL_UARTLITE | 576 | config SERIAL_UARTLITE |
578 | tristate "Xilinx uartlite serial port support" | 577 | tristate "Xilinx uartlite serial port support" |
579 | depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE | 578 | depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ |
580 | select SERIAL_CORE | 579 | select SERIAL_CORE |
581 | help | 580 | help |
582 | Say Y here if you want to use the Xilinx uartlite serial controller. | 581 | Say Y here if you want to use the Xilinx uartlite serial controller. |
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 13471dd95793..1d46966e2a65 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
@@ -604,7 +604,6 @@ static int altera_uart_remove(struct platform_device *pdev) | |||
604 | 604 | ||
605 | if (port) { | 605 | if (port) { |
606 | uart_remove_one_port(&altera_uart_driver, port); | 606 | uart_remove_one_port(&altera_uart_driver, port); |
607 | platform_set_drvdata(pdev, NULL); | ||
608 | port->mapbase = 0; | 607 | port->mapbase = 0; |
609 | } | 608 | } |
610 | 609 | ||
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e2774f9ecd59..ad41319d1d9b 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -79,13 +79,12 @@ struct vendor_data { | |||
79 | bool dma_threshold; | 79 | bool dma_threshold; |
80 | bool cts_event_workaround; | 80 | bool cts_event_workaround; |
81 | 81 | ||
82 | unsigned int (*get_fifosize)(unsigned int periphid); | 82 | unsigned int (*get_fifosize)(struct amba_device *dev); |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static unsigned int get_fifosize_arm(unsigned int periphid) | 85 | static unsigned int get_fifosize_arm(struct amba_device *dev) |
86 | { | 86 | { |
87 | unsigned int rev = (periphid >> 20) & 0xf; | 87 | return amba_rev(dev) < 3 ? 16 : 32; |
88 | return rev < 3 ? 16 : 32; | ||
89 | } | 88 | } |
90 | 89 | ||
91 | static struct vendor_data vendor_arm = { | 90 | static struct vendor_data vendor_arm = { |
@@ -98,7 +97,7 @@ static struct vendor_data vendor_arm = { | |||
98 | .get_fifosize = get_fifosize_arm, | 97 | .get_fifosize = get_fifosize_arm, |
99 | }; | 98 | }; |
100 | 99 | ||
101 | static unsigned int get_fifosize_st(unsigned int periphid) | 100 | static unsigned int get_fifosize_st(struct amba_device *dev) |
102 | { | 101 | { |
103 | return 64; | 102 | return 64; |
104 | } | 103 | } |
@@ -2157,7 +2156,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |||
2157 | uap->lcrh_rx = vendor->lcrh_rx; | 2156 | uap->lcrh_rx = vendor->lcrh_rx; |
2158 | uap->lcrh_tx = vendor->lcrh_tx; | 2157 | uap->lcrh_tx = vendor->lcrh_tx; |
2159 | uap->old_cr = 0; | 2158 | uap->old_cr = 0; |
2160 | uap->fifosize = vendor->get_fifosize(dev->periphid); | 2159 | uap->fifosize = vendor->get_fifosize(dev); |
2161 | uap->port.dev = &dev->dev; | 2160 | uap->port.dev = &dev->dev; |
2162 | uap->port.mapbase = dev->res.start; | 2161 | uap->port.mapbase = dev->res.start; |
2163 | uap->port.membase = base; | 2162 | uap->port.membase = base; |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 97f4e1858649..f7672cae5321 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c | |||
@@ -1384,7 +1384,7 @@ static int cpm_uart_probe(struct platform_device *ofdev) | |||
1384 | if (index >= UART_NR) | 1384 | if (index >= UART_NR) |
1385 | return -ENODEV; | 1385 | return -ENODEV; |
1386 | 1386 | ||
1387 | dev_set_drvdata(&ofdev->dev, pinfo); | 1387 | platform_set_drvdata(ofdev, pinfo); |
1388 | 1388 | ||
1389 | /* initialize the device pointer for the port */ | 1389 | /* initialize the device pointer for the port */ |
1390 | pinfo->port.dev = &ofdev->dev; | 1390 | pinfo->port.dev = &ofdev->dev; |
@@ -1398,7 +1398,7 @@ static int cpm_uart_probe(struct platform_device *ofdev) | |||
1398 | 1398 | ||
1399 | static int cpm_uart_remove(struct platform_device *ofdev) | 1399 | static int cpm_uart_remove(struct platform_device *ofdev) |
1400 | { | 1400 | { |
1401 | struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); | 1401 | struct uart_cpm_port *pinfo = platform_get_drvdata(ofdev); |
1402 | return uart_remove_one_port(&cpm_reg, &pinfo->port); | 1402 | return uart_remove_one_port(&cpm_reg, &pinfo->port); |
1403 | } | 1403 | } |
1404 | 1404 | ||
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 8cdfbd365892..7a761f7c9781 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -201,6 +201,7 @@ struct imx_port { | |||
201 | unsigned int old_status; | 201 | unsigned int old_status; |
202 | int txirq, rxirq, rtsirq; | 202 | int txirq, rxirq, rtsirq; |
203 | unsigned int have_rtscts:1; | 203 | unsigned int have_rtscts:1; |
204 | unsigned int dte_mode:1; | ||
204 | unsigned int use_irda:1; | 205 | unsigned int use_irda:1; |
205 | unsigned int irda_inv_rx:1; | 206 | unsigned int irda_inv_rx:1; |
206 | unsigned int irda_inv_tx:1; | 207 | unsigned int irda_inv_tx:1; |
@@ -271,6 +272,7 @@ static inline int is_imx21_uart(struct imx_port *sport) | |||
271 | /* | 272 | /* |
272 | * Save and restore functions for UCR1, UCR2 and UCR3 registers | 273 | * Save and restore functions for UCR1, UCR2 and UCR3 registers |
273 | */ | 274 | */ |
275 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_IMX_CONSOLE) | ||
274 | static void imx_port_ucrs_save(struct uart_port *port, | 276 | static void imx_port_ucrs_save(struct uart_port *port, |
275 | struct imx_port_ucrs *ucr) | 277 | struct imx_port_ucrs *ucr) |
276 | { | 278 | { |
@@ -288,6 +290,7 @@ static void imx_port_ucrs_restore(struct uart_port *port, | |||
288 | writel(ucr->ucr2, port->membase + UCR2); | 290 | writel(ucr->ucr2, port->membase + UCR2); |
289 | writel(ucr->ucr3, port->membase + UCR3); | 291 | writel(ucr->ucr3, port->membase + UCR3); |
290 | } | 292 | } |
293 | #endif | ||
291 | 294 | ||
292 | /* | 295 | /* |
293 | * Handle any change of modem status signal since we were last called. | 296 | * Handle any change of modem status signal since we were last called. |
@@ -449,6 +452,13 @@ static void imx_start_tx(struct uart_port *port) | |||
449 | temp &= ~(UCR1_RRDYEN); | 452 | temp &= ~(UCR1_RRDYEN); |
450 | writel(temp, sport->port.membase + UCR1); | 453 | writel(temp, sport->port.membase + UCR1); |
451 | } | 454 | } |
455 | /* Clear any pending ORE flag before enabling interrupt */ | ||
456 | temp = readl(sport->port.membase + USR2); | ||
457 | writel(temp | USR2_ORE, sport->port.membase + USR2); | ||
458 | |||
459 | temp = readl(sport->port.membase + UCR4); | ||
460 | temp |= UCR4_OREN; | ||
461 | writel(temp, sport->port.membase + UCR4); | ||
452 | 462 | ||
453 | temp = readl(sport->port.membase + UCR1); | 463 | temp = readl(sport->port.membase + UCR1); |
454 | writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); | 464 | writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); |
@@ -582,6 +592,7 @@ static irqreturn_t imx_int(int irq, void *dev_id) | |||
582 | { | 592 | { |
583 | struct imx_port *sport = dev_id; | 593 | struct imx_port *sport = dev_id; |
584 | unsigned int sts; | 594 | unsigned int sts; |
595 | unsigned int sts2; | ||
585 | 596 | ||
586 | sts = readl(sport->port.membase + USR1); | 597 | sts = readl(sport->port.membase + USR1); |
587 | 598 | ||
@@ -598,6 +609,13 @@ static irqreturn_t imx_int(int irq, void *dev_id) | |||
598 | if (sts & USR1_AWAKE) | 609 | if (sts & USR1_AWAKE) |
599 | writel(USR1_AWAKE, sport->port.membase + USR1); | 610 | writel(USR1_AWAKE, sport->port.membase + USR1); |
600 | 611 | ||
612 | sts2 = readl(sport->port.membase + USR2); | ||
613 | if (sts2 & USR2_ORE) { | ||
614 | dev_err(sport->port.dev, "Rx FIFO overrun\n"); | ||
615 | sport->port.icount.overrun++; | ||
616 | writel(sts2 | USR2_ORE, sport->port.membase + USR2); | ||
617 | } | ||
618 | |||
601 | return IRQ_HANDLED; | 619 | return IRQ_HANDLED; |
602 | } | 620 | } |
603 | 621 | ||
@@ -684,6 +702,14 @@ static int imx_startup(struct uart_port *port) | |||
684 | int retval; | 702 | int retval; |
685 | unsigned long flags, temp; | 703 | unsigned long flags, temp; |
686 | 704 | ||
705 | retval = clk_prepare_enable(sport->clk_per); | ||
706 | if (retval) | ||
707 | goto error_out1; | ||
708 | |||
709 | retval = clk_prepare_enable(sport->clk_ipg); | ||
710 | if (retval) | ||
711 | goto error_out1; | ||
712 | |||
687 | imx_setup_ufcr(sport, 0); | 713 | imx_setup_ufcr(sport, 0); |
688 | 714 | ||
689 | /* disable the DREN bit (Data Ready interrupt enable) before | 715 | /* disable the DREN bit (Data Ready interrupt enable) before |
@@ -871,6 +897,9 @@ static void imx_shutdown(struct uart_port *port) | |||
871 | 897 | ||
872 | writel(temp, sport->port.membase + UCR1); | 898 | writel(temp, sport->port.membase + UCR1); |
873 | spin_unlock_irqrestore(&sport->port.lock, flags); | 899 | spin_unlock_irqrestore(&sport->port.lock, flags); |
900 | |||
901 | clk_disable_unprepare(sport->clk_per); | ||
902 | clk_disable_unprepare(sport->clk_ipg); | ||
874 | } | 903 | } |
875 | 904 | ||
876 | static void | 905 | static void |
@@ -1007,6 +1036,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1007 | 1036 | ||
1008 | ufcr = readl(sport->port.membase + UFCR); | 1037 | ufcr = readl(sport->port.membase + UFCR); |
1009 | ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); | 1038 | ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); |
1039 | if (sport->dte_mode) | ||
1040 | ufcr |= UFCR_DCEDTE; | ||
1010 | writel(ufcr, sport->port.membase + UFCR); | 1041 | writel(ufcr, sport->port.membase + UFCR); |
1011 | 1042 | ||
1012 | writel(num, sport->port.membase + UBIR); | 1043 | writel(num, sport->port.membase + UBIR); |
@@ -1431,6 +1462,9 @@ static int serial_imx_probe_dt(struct imx_port *sport, | |||
1431 | if (of_get_property(np, "fsl,irda-mode", NULL)) | 1462 | if (of_get_property(np, "fsl,irda-mode", NULL)) |
1432 | sport->use_irda = 1; | 1463 | sport->use_irda = 1; |
1433 | 1464 | ||
1465 | if (of_get_property(np, "fsl,dte-mode", NULL)) | ||
1466 | sport->dte_mode = 1; | ||
1467 | |||
1434 | sport->devdata = of_id->data; | 1468 | sport->devdata = of_id->data; |
1435 | 1469 | ||
1436 | return 0; | 1470 | return 0; |
@@ -1544,6 +1578,9 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1544 | goto deinit; | 1578 | goto deinit; |
1545 | platform_set_drvdata(pdev, sport); | 1579 | platform_set_drvdata(pdev, sport); |
1546 | 1580 | ||
1581 | clk_disable_unprepare(sport->clk_per); | ||
1582 | clk_disable_unprepare(sport->clk_ipg); | ||
1583 | |||
1547 | return 0; | 1584 | return 0; |
1548 | deinit: | 1585 | deinit: |
1549 | if (pdata && pdata->exit) | 1586 | if (pdata && pdata->exit) |
@@ -1565,9 +1602,6 @@ static int serial_imx_remove(struct platform_device *pdev) | |||
1565 | 1602 | ||
1566 | uart_remove_one_port(&imx_reg, &sport->port); | 1603 | uart_remove_one_port(&imx_reg, &sport->port); |
1567 | 1604 | ||
1568 | clk_disable_unprepare(sport->clk_per); | ||
1569 | clk_disable_unprepare(sport->clk_ipg); | ||
1570 | |||
1571 | if (pdata && pdata->exit) | 1605 | if (pdata && pdata->exit) |
1572 | pdata->exit(pdev); | 1606 | pdata->exit(pdev); |
1573 | 1607 | ||
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index f51b280f3bf2..9ba194590a80 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -84,16 +84,6 @@ static void mpc52xx_uart_of_enumerate(void); | |||
84 | static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); | 84 | static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); |
85 | static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port); | 85 | static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port); |
86 | 86 | ||
87 | |||
88 | /* Simple macro to test if a port is console or not. This one is taken | ||
89 | * for serial_core.c and maybe should be moved to serial_core.h ? */ | ||
90 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | ||
91 | #define uart_console(port) \ | ||
92 | ((port)->cons && (port)->cons->index == (port)->line) | ||
93 | #else | ||
94 | #define uart_console(port) (0) | ||
95 | #endif | ||
96 | |||
97 | /* ======================================================================== */ | 87 | /* ======================================================================== */ |
98 | /* PSC fifo operations for isolating differences between 52xx and 512x */ | 88 | /* PSC fifo operations for isolating differences between 52xx and 512x */ |
99 | /* ======================================================================== */ | 89 | /* ======================================================================== */ |
@@ -122,6 +112,15 @@ struct psc_ops { | |||
122 | void (*fifoc_uninit)(void); | 112 | void (*fifoc_uninit)(void); |
123 | void (*get_irq)(struct uart_port *, struct device_node *); | 113 | void (*get_irq)(struct uart_port *, struct device_node *); |
124 | irqreturn_t (*handle_irq)(struct uart_port *port); | 114 | irqreturn_t (*handle_irq)(struct uart_port *port); |
115 | u16 (*get_status)(struct uart_port *port); | ||
116 | u8 (*get_ipcr)(struct uart_port *port); | ||
117 | void (*command)(struct uart_port *port, u8 cmd); | ||
118 | void (*set_mode)(struct uart_port *port, u8 mr1, u8 mr2); | ||
119 | void (*set_rts)(struct uart_port *port, int state); | ||
120 | void (*enable_ms)(struct uart_port *port); | ||
121 | void (*set_sicr)(struct uart_port *port, u32 val); | ||
122 | void (*set_imr)(struct uart_port *port, u16 val); | ||
123 | u8 (*get_mr1)(struct uart_port *port); | ||
125 | }; | 124 | }; |
126 | 125 | ||
127 | /* setting the prescaler and divisor reg is common for all chips */ | 126 | /* setting the prescaler and divisor reg is common for all chips */ |
@@ -134,6 +133,65 @@ static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc, | |||
134 | out_8(&psc->ctlr, divisor & 0xff); | 133 | out_8(&psc->ctlr, divisor & 0xff); |
135 | } | 134 | } |
136 | 135 | ||
136 | static u16 mpc52xx_psc_get_status(struct uart_port *port) | ||
137 | { | ||
138 | return in_be16(&PSC(port)->mpc52xx_psc_status); | ||
139 | } | ||
140 | |||
141 | static u8 mpc52xx_psc_get_ipcr(struct uart_port *port) | ||
142 | { | ||
143 | return in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
144 | } | ||
145 | |||
146 | static void mpc52xx_psc_command(struct uart_port *port, u8 cmd) | ||
147 | { | ||
148 | out_8(&PSC(port)->command, cmd); | ||
149 | } | ||
150 | |||
151 | static void mpc52xx_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2) | ||
152 | { | ||
153 | out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
154 | out_8(&PSC(port)->mode, mr1); | ||
155 | out_8(&PSC(port)->mode, mr2); | ||
156 | } | ||
157 | |||
158 | static void mpc52xx_psc_set_rts(struct uart_port *port, int state) | ||
159 | { | ||
160 | if (state) | ||
161 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
162 | else | ||
163 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
164 | } | ||
165 | |||
166 | static void mpc52xx_psc_enable_ms(struct uart_port *port) | ||
167 | { | ||
168 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
169 | |||
170 | /* clear D_*-bits by reading them */ | ||
171 | in_8(&psc->mpc52xx_psc_ipcr); | ||
172 | /* enable CTS and DCD as IPC interrupts */ | ||
173 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
174 | |||
175 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
176 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
177 | } | ||
178 | |||
179 | static void mpc52xx_psc_set_sicr(struct uart_port *port, u32 val) | ||
180 | { | ||
181 | out_be32(&PSC(port)->sicr, val); | ||
182 | } | ||
183 | |||
184 | static void mpc52xx_psc_set_imr(struct uart_port *port, u16 val) | ||
185 | { | ||
186 | out_be16(&PSC(port)->mpc52xx_psc_imr, val); | ||
187 | } | ||
188 | |||
189 | static u8 mpc52xx_psc_get_mr1(struct uart_port *port) | ||
190 | { | ||
191 | out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
192 | return in_8(&PSC(port)->mode); | ||
193 | } | ||
194 | |||
137 | #ifdef CONFIG_PPC_MPC52xx | 195 | #ifdef CONFIG_PPC_MPC52xx |
138 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | 196 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) |
139 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | 197 | static void mpc52xx_psc_fifo_init(struct uart_port *port) |
@@ -304,6 +362,15 @@ static struct psc_ops mpc52xx_psc_ops = { | |||
304 | .set_baudrate = mpc5200_psc_set_baudrate, | 362 | .set_baudrate = mpc5200_psc_set_baudrate, |
305 | .get_irq = mpc52xx_psc_get_irq, | 363 | .get_irq = mpc52xx_psc_get_irq, |
306 | .handle_irq = mpc52xx_psc_handle_irq, | 364 | .handle_irq = mpc52xx_psc_handle_irq, |
365 | .get_status = mpc52xx_psc_get_status, | ||
366 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
367 | .command = mpc52xx_psc_command, | ||
368 | .set_mode = mpc52xx_psc_set_mode, | ||
369 | .set_rts = mpc52xx_psc_set_rts, | ||
370 | .enable_ms = mpc52xx_psc_enable_ms, | ||
371 | .set_sicr = mpc52xx_psc_set_sicr, | ||
372 | .set_imr = mpc52xx_psc_set_imr, | ||
373 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
307 | }; | 374 | }; |
308 | 375 | ||
309 | static struct psc_ops mpc5200b_psc_ops = { | 376 | static struct psc_ops mpc5200b_psc_ops = { |
@@ -325,6 +392,15 @@ static struct psc_ops mpc5200b_psc_ops = { | |||
325 | .set_baudrate = mpc5200b_psc_set_baudrate, | 392 | .set_baudrate = mpc5200b_psc_set_baudrate, |
326 | .get_irq = mpc52xx_psc_get_irq, | 393 | .get_irq = mpc52xx_psc_get_irq, |
327 | .handle_irq = mpc52xx_psc_handle_irq, | 394 | .handle_irq = mpc52xx_psc_handle_irq, |
395 | .get_status = mpc52xx_psc_get_status, | ||
396 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
397 | .command = mpc52xx_psc_command, | ||
398 | .set_mode = mpc52xx_psc_set_mode, | ||
399 | .set_rts = mpc52xx_psc_set_rts, | ||
400 | .enable_ms = mpc52xx_psc_enable_ms, | ||
401 | .set_sicr = mpc52xx_psc_set_sicr, | ||
402 | .set_imr = mpc52xx_psc_set_imr, | ||
403 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
328 | }; | 404 | }; |
329 | 405 | ||
330 | #endif /* CONFIG_MPC52xx */ | 406 | #endif /* CONFIG_MPC52xx */ |
@@ -572,6 +648,246 @@ static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np) | |||
572 | port->irqflags = IRQF_SHARED; | 648 | port->irqflags = IRQF_SHARED; |
573 | port->irq = psc_fifoc_irq; | 649 | port->irq = psc_fifoc_irq; |
574 | } | 650 | } |
651 | #endif | ||
652 | |||
653 | #ifdef CONFIG_PPC_MPC512x | ||
654 | |||
655 | #define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase)) | ||
656 | #define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1)) | ||
657 | |||
658 | static void mpc5125_psc_fifo_init(struct uart_port *port) | ||
659 | { | ||
660 | /* /32 prescaler */ | ||
661 | out_8(&PSC_5125(port)->mpc52xx_psc_clock_select, 0xdd); | ||
662 | |||
663 | out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
664 | out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
665 | out_be32(&FIFO_5125(port)->txalarm, 1); | ||
666 | out_be32(&FIFO_5125(port)->tximr, 0); | ||
667 | |||
668 | out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
669 | out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
670 | out_be32(&FIFO_5125(port)->rxalarm, 1); | ||
671 | out_be32(&FIFO_5125(port)->rximr, 0); | ||
672 | |||
673 | out_be32(&FIFO_5125(port)->tximr, MPC512x_PSC_FIFO_ALARM); | ||
674 | out_be32(&FIFO_5125(port)->rximr, MPC512x_PSC_FIFO_ALARM); | ||
675 | } | ||
676 | |||
677 | static int mpc5125_psc_raw_rx_rdy(struct uart_port *port) | ||
678 | { | ||
679 | return !(in_be32(&FIFO_5125(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY); | ||
680 | } | ||
681 | |||
682 | static int mpc5125_psc_raw_tx_rdy(struct uart_port *port) | ||
683 | { | ||
684 | return !(in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_FULL); | ||
685 | } | ||
686 | |||
687 | static int mpc5125_psc_rx_rdy(struct uart_port *port) | ||
688 | { | ||
689 | return in_be32(&FIFO_5125(port)->rxsr) & | ||
690 | in_be32(&FIFO_5125(port)->rximr) & MPC512x_PSC_FIFO_ALARM; | ||
691 | } | ||
692 | |||
693 | static int mpc5125_psc_tx_rdy(struct uart_port *port) | ||
694 | { | ||
695 | return in_be32(&FIFO_5125(port)->txsr) & | ||
696 | in_be32(&FIFO_5125(port)->tximr) & MPC512x_PSC_FIFO_ALARM; | ||
697 | } | ||
698 | |||
699 | static int mpc5125_psc_tx_empty(struct uart_port *port) | ||
700 | { | ||
701 | return in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_EMPTY; | ||
702 | } | ||
703 | |||
704 | static void mpc5125_psc_stop_rx(struct uart_port *port) | ||
705 | { | ||
706 | unsigned long rx_fifo_imr; | ||
707 | |||
708 | rx_fifo_imr = in_be32(&FIFO_5125(port)->rximr); | ||
709 | rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
710 | out_be32(&FIFO_5125(port)->rximr, rx_fifo_imr); | ||
711 | } | ||
712 | |||
713 | static void mpc5125_psc_start_tx(struct uart_port *port) | ||
714 | { | ||
715 | unsigned long tx_fifo_imr; | ||
716 | |||
717 | tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr); | ||
718 | tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM; | ||
719 | out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr); | ||
720 | } | ||
721 | |||
722 | static void mpc5125_psc_stop_tx(struct uart_port *port) | ||
723 | { | ||
724 | unsigned long tx_fifo_imr; | ||
725 | |||
726 | tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr); | ||
727 | tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
728 | out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr); | ||
729 | } | ||
730 | |||
731 | static void mpc5125_psc_rx_clr_irq(struct uart_port *port) | ||
732 | { | ||
733 | out_be32(&FIFO_5125(port)->rxisr, in_be32(&FIFO_5125(port)->rxisr)); | ||
734 | } | ||
735 | |||
736 | static void mpc5125_psc_tx_clr_irq(struct uart_port *port) | ||
737 | { | ||
738 | out_be32(&FIFO_5125(port)->txisr, in_be32(&FIFO_5125(port)->txisr)); | ||
739 | } | ||
740 | |||
741 | static void mpc5125_psc_write_char(struct uart_port *port, unsigned char c) | ||
742 | { | ||
743 | out_8(&FIFO_5125(port)->txdata_8, c); | ||
744 | } | ||
745 | |||
746 | static unsigned char mpc5125_psc_read_char(struct uart_port *port) | ||
747 | { | ||
748 | return in_8(&FIFO_5125(port)->rxdata_8); | ||
749 | } | ||
750 | |||
751 | static void mpc5125_psc_cw_disable_ints(struct uart_port *port) | ||
752 | { | ||
753 | port->read_status_mask = | ||
754 | in_be32(&FIFO_5125(port)->tximr) << 16 | | ||
755 | in_be32(&FIFO_5125(port)->rximr); | ||
756 | out_be32(&FIFO_5125(port)->tximr, 0); | ||
757 | out_be32(&FIFO_5125(port)->rximr, 0); | ||
758 | } | ||
759 | |||
760 | static void mpc5125_psc_cw_restore_ints(struct uart_port *port) | ||
761 | { | ||
762 | out_be32(&FIFO_5125(port)->tximr, | ||
763 | (port->read_status_mask >> 16) & 0x7f); | ||
764 | out_be32(&FIFO_5125(port)->rximr, port->read_status_mask & 0x7f); | ||
765 | } | ||
766 | |||
767 | static inline void mpc5125_set_divisor(struct mpc5125_psc __iomem *psc, | ||
768 | u8 prescaler, unsigned int divisor) | ||
769 | { | ||
770 | /* select prescaler */ | ||
771 | out_8(&psc->mpc52xx_psc_clock_select, prescaler); | ||
772 | out_8(&psc->ctur, divisor >> 8); | ||
773 | out_8(&psc->ctlr, divisor & 0xff); | ||
774 | } | ||
775 | |||
776 | static unsigned int mpc5125_psc_set_baudrate(struct uart_port *port, | ||
777 | struct ktermios *new, | ||
778 | struct ktermios *old) | ||
779 | { | ||
780 | unsigned int baud; | ||
781 | unsigned int divisor; | ||
782 | |||
783 | /* | ||
784 | * Calculate with a /16 prescaler here. | ||
785 | */ | ||
786 | |||
787 | /* uartclk contains the ips freq */ | ||
788 | baud = uart_get_baud_rate(port, new, old, | ||
789 | port->uartclk / (16 * 0xffff) + 1, | ||
790 | port->uartclk / 16); | ||
791 | divisor = (port->uartclk + 8 * baud) / (16 * baud); | ||
792 | |||
793 | /* enable the /16 prescaler and set the divisor */ | ||
794 | mpc5125_set_divisor(PSC_5125(port), 0xdd, divisor); | ||
795 | return baud; | ||
796 | } | ||
797 | |||
798 | /* | ||
799 | * MPC5125 have compatible PSC FIFO Controller. | ||
800 | * Special init not needed. | ||
801 | */ | ||
802 | static u16 mpc5125_psc_get_status(struct uart_port *port) | ||
803 | { | ||
804 | return in_be16(&PSC_5125(port)->mpc52xx_psc_status); | ||
805 | } | ||
806 | |||
807 | static u8 mpc5125_psc_get_ipcr(struct uart_port *port) | ||
808 | { | ||
809 | return in_8(&PSC_5125(port)->mpc52xx_psc_ipcr); | ||
810 | } | ||
811 | |||
812 | static void mpc5125_psc_command(struct uart_port *port, u8 cmd) | ||
813 | { | ||
814 | out_8(&PSC_5125(port)->command, cmd); | ||
815 | } | ||
816 | |||
817 | static void mpc5125_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2) | ||
818 | { | ||
819 | out_8(&PSC_5125(port)->mr1, mr1); | ||
820 | out_8(&PSC_5125(port)->mr2, mr2); | ||
821 | } | ||
822 | |||
823 | static void mpc5125_psc_set_rts(struct uart_port *port, int state) | ||
824 | { | ||
825 | if (state & TIOCM_RTS) | ||
826 | out_8(&PSC_5125(port)->op1, MPC52xx_PSC_OP_RTS); | ||
827 | else | ||
828 | out_8(&PSC_5125(port)->op0, MPC52xx_PSC_OP_RTS); | ||
829 | } | ||
830 | |||
831 | static void mpc5125_psc_enable_ms(struct uart_port *port) | ||
832 | { | ||
833 | struct mpc5125_psc __iomem *psc = PSC_5125(port); | ||
834 | |||
835 | /* clear D_*-bits by reading them */ | ||
836 | in_8(&psc->mpc52xx_psc_ipcr); | ||
837 | /* enable CTS and DCD as IPC interrupts */ | ||
838 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
839 | |||
840 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
841 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
842 | } | ||
843 | |||
844 | static void mpc5125_psc_set_sicr(struct uart_port *port, u32 val) | ||
845 | { | ||
846 | out_be32(&PSC_5125(port)->sicr, val); | ||
847 | } | ||
848 | |||
849 | static void mpc5125_psc_set_imr(struct uart_port *port, u16 val) | ||
850 | { | ||
851 | out_be16(&PSC_5125(port)->mpc52xx_psc_imr, val); | ||
852 | } | ||
853 | |||
854 | static u8 mpc5125_psc_get_mr1(struct uart_port *port) | ||
855 | { | ||
856 | return in_8(&PSC_5125(port)->mr1); | ||
857 | } | ||
858 | |||
859 | static struct psc_ops mpc5125_psc_ops = { | ||
860 | .fifo_init = mpc5125_psc_fifo_init, | ||
861 | .raw_rx_rdy = mpc5125_psc_raw_rx_rdy, | ||
862 | .raw_tx_rdy = mpc5125_psc_raw_tx_rdy, | ||
863 | .rx_rdy = mpc5125_psc_rx_rdy, | ||
864 | .tx_rdy = mpc5125_psc_tx_rdy, | ||
865 | .tx_empty = mpc5125_psc_tx_empty, | ||
866 | .stop_rx = mpc5125_psc_stop_rx, | ||
867 | .start_tx = mpc5125_psc_start_tx, | ||
868 | .stop_tx = mpc5125_psc_stop_tx, | ||
869 | .rx_clr_irq = mpc5125_psc_rx_clr_irq, | ||
870 | .tx_clr_irq = mpc5125_psc_tx_clr_irq, | ||
871 | .write_char = mpc5125_psc_write_char, | ||
872 | .read_char = mpc5125_psc_read_char, | ||
873 | .cw_disable_ints = mpc5125_psc_cw_disable_ints, | ||
874 | .cw_restore_ints = mpc5125_psc_cw_restore_ints, | ||
875 | .set_baudrate = mpc5125_psc_set_baudrate, | ||
876 | .clock = mpc512x_psc_clock, | ||
877 | .fifoc_init = mpc512x_psc_fifoc_init, | ||
878 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, | ||
879 | .get_irq = mpc512x_psc_get_irq, | ||
880 | .handle_irq = mpc512x_psc_handle_irq, | ||
881 | .get_status = mpc5125_psc_get_status, | ||
882 | .get_ipcr = mpc5125_psc_get_ipcr, | ||
883 | .command = mpc5125_psc_command, | ||
884 | .set_mode = mpc5125_psc_set_mode, | ||
885 | .set_rts = mpc5125_psc_set_rts, | ||
886 | .enable_ms = mpc5125_psc_enable_ms, | ||
887 | .set_sicr = mpc5125_psc_set_sicr, | ||
888 | .set_imr = mpc5125_psc_set_imr, | ||
889 | .get_mr1 = mpc5125_psc_get_mr1, | ||
890 | }; | ||
575 | 891 | ||
576 | static struct psc_ops mpc512x_psc_ops = { | 892 | static struct psc_ops mpc512x_psc_ops = { |
577 | .fifo_init = mpc512x_psc_fifo_init, | 893 | .fifo_init = mpc512x_psc_fifo_init, |
@@ -595,8 +911,18 @@ static struct psc_ops mpc512x_psc_ops = { | |||
595 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, | 911 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, |
596 | .get_irq = mpc512x_psc_get_irq, | 912 | .get_irq = mpc512x_psc_get_irq, |
597 | .handle_irq = mpc512x_psc_handle_irq, | 913 | .handle_irq = mpc512x_psc_handle_irq, |
914 | .get_status = mpc52xx_psc_get_status, | ||
915 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
916 | .command = mpc52xx_psc_command, | ||
917 | .set_mode = mpc52xx_psc_set_mode, | ||
918 | .set_rts = mpc52xx_psc_set_rts, | ||
919 | .enable_ms = mpc52xx_psc_enable_ms, | ||
920 | .set_sicr = mpc52xx_psc_set_sicr, | ||
921 | .set_imr = mpc52xx_psc_set_imr, | ||
922 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
598 | }; | 923 | }; |
599 | #endif | 924 | #endif /* CONFIG_PPC_MPC512x */ |
925 | |||
600 | 926 | ||
601 | static const struct psc_ops *psc_ops; | 927 | static const struct psc_ops *psc_ops; |
602 | 928 | ||
@@ -613,17 +939,14 @@ mpc52xx_uart_tx_empty(struct uart_port *port) | |||
613 | static void | 939 | static void |
614 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 940 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
615 | { | 941 | { |
616 | if (mctrl & TIOCM_RTS) | 942 | psc_ops->set_rts(port, mctrl & TIOCM_RTS); |
617 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
618 | else | ||
619 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
620 | } | 943 | } |
621 | 944 | ||
622 | static unsigned int | 945 | static unsigned int |
623 | mpc52xx_uart_get_mctrl(struct uart_port *port) | 946 | mpc52xx_uart_get_mctrl(struct uart_port *port) |
624 | { | 947 | { |
625 | unsigned int ret = TIOCM_DSR; | 948 | unsigned int ret = TIOCM_DSR; |
626 | u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | 949 | u8 status = psc_ops->get_ipcr(port); |
627 | 950 | ||
628 | if (!(status & MPC52xx_PSC_CTS)) | 951 | if (!(status & MPC52xx_PSC_CTS)) |
629 | ret |= TIOCM_CTS; | 952 | ret |= TIOCM_CTS; |
@@ -673,15 +996,7 @@ mpc52xx_uart_stop_rx(struct uart_port *port) | |||
673 | static void | 996 | static void |
674 | mpc52xx_uart_enable_ms(struct uart_port *port) | 997 | mpc52xx_uart_enable_ms(struct uart_port *port) |
675 | { | 998 | { |
676 | struct mpc52xx_psc __iomem *psc = PSC(port); | 999 | psc_ops->enable_ms(port); |
677 | |||
678 | /* clear D_*-bits by reading them */ | ||
679 | in_8(&psc->mpc52xx_psc_ipcr); | ||
680 | /* enable CTS and DCD as IPC interrupts */ | ||
681 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
682 | |||
683 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
684 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
685 | } | 1000 | } |
686 | 1001 | ||
687 | static void | 1002 | static void |
@@ -691,9 +1006,9 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
691 | spin_lock_irqsave(&port->lock, flags); | 1006 | spin_lock_irqsave(&port->lock, flags); |
692 | 1007 | ||
693 | if (ctl == -1) | 1008 | if (ctl == -1) |
694 | out_8(&PSC(port)->command, MPC52xx_PSC_START_BRK); | 1009 | psc_ops->command(port, MPC52xx_PSC_START_BRK); |
695 | else | 1010 | else |
696 | out_8(&PSC(port)->command, MPC52xx_PSC_STOP_BRK); | 1011 | psc_ops->command(port, MPC52xx_PSC_STOP_BRK); |
697 | 1012 | ||
698 | spin_unlock_irqrestore(&port->lock, flags); | 1013 | spin_unlock_irqrestore(&port->lock, flags); |
699 | } | 1014 | } |
@@ -701,7 +1016,6 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
701 | static int | 1016 | static int |
702 | mpc52xx_uart_startup(struct uart_port *port) | 1017 | mpc52xx_uart_startup(struct uart_port *port) |
703 | { | 1018 | { |
704 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
705 | int ret; | 1019 | int ret; |
706 | 1020 | ||
707 | if (psc_ops->clock) { | 1021 | if (psc_ops->clock) { |
@@ -717,15 +1031,15 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
717 | return ret; | 1031 | return ret; |
718 | 1032 | ||
719 | /* Reset/activate the port, clear and enable interrupts */ | 1033 | /* Reset/activate the port, clear and enable interrupts */ |
720 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 1034 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
721 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 1035 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
722 | 1036 | ||
723 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | 1037 | psc_ops->set_sicr(port, 0); /* UART mode DCD ignored */ |
724 | 1038 | ||
725 | psc_ops->fifo_init(port); | 1039 | psc_ops->fifo_init(port); |
726 | 1040 | ||
727 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 1041 | psc_ops->command(port, MPC52xx_PSC_TX_ENABLE); |
728 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 1042 | psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); |
729 | 1043 | ||
730 | return 0; | 1044 | return 0; |
731 | } | 1045 | } |
@@ -733,15 +1047,13 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
733 | static void | 1047 | static void |
734 | mpc52xx_uart_shutdown(struct uart_port *port) | 1048 | mpc52xx_uart_shutdown(struct uart_port *port) |
735 | { | 1049 | { |
736 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
737 | |||
738 | /* Shut down the port. Leave TX active if on a console port */ | 1050 | /* Shut down the port. Leave TX active if on a console port */ |
739 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 1051 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
740 | if (!uart_console(port)) | 1052 | if (!uart_console(port)) |
741 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 1053 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
742 | 1054 | ||
743 | port->read_status_mask = 0; | 1055 | port->read_status_mask = 0; |
744 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 1056 | psc_ops->set_imr(port, port->read_status_mask); |
745 | 1057 | ||
746 | if (psc_ops->clock) | 1058 | if (psc_ops->clock) |
747 | psc_ops->clock(port, 0); | 1059 | psc_ops->clock(port, 0); |
@@ -754,7 +1066,6 @@ static void | |||
754 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | 1066 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, |
755 | struct ktermios *old) | 1067 | struct ktermios *old) |
756 | { | 1068 | { |
757 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
758 | unsigned long flags; | 1069 | unsigned long flags; |
759 | unsigned char mr1, mr2; | 1070 | unsigned char mr1, mr2; |
760 | unsigned int j; | 1071 | unsigned int j; |
@@ -818,13 +1129,11 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
818 | "Some chars may have been lost.\n"); | 1129 | "Some chars may have been lost.\n"); |
819 | 1130 | ||
820 | /* Reset the TX & RX */ | 1131 | /* Reset the TX & RX */ |
821 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 1132 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
822 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 1133 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
823 | 1134 | ||
824 | /* Send new mode settings */ | 1135 | /* Send new mode settings */ |
825 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | 1136 | psc_ops->set_mode(port, mr1, mr2); |
826 | out_8(&psc->mode, mr1); | ||
827 | out_8(&psc->mode, mr2); | ||
828 | baud = psc_ops->set_baudrate(port, new, old); | 1137 | baud = psc_ops->set_baudrate(port, new, old); |
829 | 1138 | ||
830 | /* Update the per-port timeout */ | 1139 | /* Update the per-port timeout */ |
@@ -834,8 +1143,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
834 | mpc52xx_uart_enable_ms(port); | 1143 | mpc52xx_uart_enable_ms(port); |
835 | 1144 | ||
836 | /* Reenable TX & RX */ | 1145 | /* Reenable TX & RX */ |
837 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 1146 | psc_ops->command(port, MPC52xx_PSC_TX_ENABLE); |
838 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 1147 | psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); |
839 | 1148 | ||
840 | /* We're all set, release the lock */ | 1149 | /* We're all set, release the lock */ |
841 | spin_unlock_irqrestore(&port->lock, flags); | 1150 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -963,7 +1272,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
963 | flag = TTY_NORMAL; | 1272 | flag = TTY_NORMAL; |
964 | port->icount.rx++; | 1273 | port->icount.rx++; |
965 | 1274 | ||
966 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | 1275 | status = psc_ops->get_status(port); |
967 | 1276 | ||
968 | if (status & (MPC52xx_PSC_SR_PE | | 1277 | if (status & (MPC52xx_PSC_SR_PE | |
969 | MPC52xx_PSC_SR_FE | | 1278 | MPC52xx_PSC_SR_FE | |
@@ -983,7 +1292,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
983 | } | 1292 | } |
984 | 1293 | ||
985 | /* Clear error condition */ | 1294 | /* Clear error condition */ |
986 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); | 1295 | psc_ops->command(port, MPC52xx_PSC_RST_ERR_STAT); |
987 | 1296 | ||
988 | } | 1297 | } |
989 | tty_insert_flip_char(tport, ch, flag); | 1298 | tty_insert_flip_char(tport, ch, flag); |
@@ -1066,7 +1375,7 @@ mpc5xxx_uart_process_int(struct uart_port *port) | |||
1066 | if (psc_ops->tx_rdy(port)) | 1375 | if (psc_ops->tx_rdy(port)) |
1067 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 1376 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
1068 | 1377 | ||
1069 | status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | 1378 | status = psc_ops->get_ipcr(port); |
1070 | if (status & MPC52xx_PSC_D_DCD) | 1379 | if (status & MPC52xx_PSC_D_DCD) |
1071 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); | 1380 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); |
1072 | 1381 | ||
@@ -1107,14 +1416,12 @@ static void __init | |||
1107 | mpc52xx_console_get_options(struct uart_port *port, | 1416 | mpc52xx_console_get_options(struct uart_port *port, |
1108 | int *baud, int *parity, int *bits, int *flow) | 1417 | int *baud, int *parity, int *bits, int *flow) |
1109 | { | 1418 | { |
1110 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
1111 | unsigned char mr1; | 1419 | unsigned char mr1; |
1112 | 1420 | ||
1113 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); | 1421 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); |
1114 | 1422 | ||
1115 | /* Read the mode registers */ | 1423 | /* Read the mode registers */ |
1116 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | 1424 | mr1 = psc_ops->get_mr1(port); |
1117 | mr1 = in_8(&psc->mode); | ||
1118 | 1425 | ||
1119 | /* CT{U,L}R are write-only ! */ | 1426 | /* CT{U,L}R are write-only ! */ |
1120 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | 1427 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; |
@@ -1304,6 +1611,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
1304 | #endif | 1611 | #endif |
1305 | #ifdef CONFIG_PPC_MPC512x | 1612 | #ifdef CONFIG_PPC_MPC512x |
1306 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, | 1613 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, |
1614 | { .compatible = "fsl,mpc5125-psc-uart", .data = &mpc5125_psc_ops, }, | ||
1307 | #endif | 1615 | #endif |
1308 | {}, | 1616 | {}, |
1309 | }; | 1617 | }; |
@@ -1372,15 +1680,14 @@ static int mpc52xx_uart_of_probe(struct platform_device *op) | |||
1372 | if (ret) | 1680 | if (ret) |
1373 | return ret; | 1681 | return ret; |
1374 | 1682 | ||
1375 | dev_set_drvdata(&op->dev, (void *)port); | 1683 | platform_set_drvdata(op, (void *)port); |
1376 | return 0; | 1684 | return 0; |
1377 | } | 1685 | } |
1378 | 1686 | ||
1379 | static int | 1687 | static int |
1380 | mpc52xx_uart_of_remove(struct platform_device *op) | 1688 | mpc52xx_uart_of_remove(struct platform_device *op) |
1381 | { | 1689 | { |
1382 | struct uart_port *port = dev_get_drvdata(&op->dev); | 1690 | struct uart_port *port = platform_get_drvdata(op); |
1383 | dev_set_drvdata(&op->dev, NULL); | ||
1384 | 1691 | ||
1385 | if (port) | 1692 | if (port) |
1386 | uart_remove_one_port(&mpc52xx_uart_driver, port); | 1693 | uart_remove_one_port(&mpc52xx_uart_driver, port); |
@@ -1392,7 +1699,7 @@ mpc52xx_uart_of_remove(struct platform_device *op) | |||
1392 | static int | 1699 | static int |
1393 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) | 1700 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) |
1394 | { | 1701 | { |
1395 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1702 | struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); |
1396 | 1703 | ||
1397 | if (port) | 1704 | if (port) |
1398 | uart_suspend_port(&mpc52xx_uart_driver, port); | 1705 | uart_suspend_port(&mpc52xx_uart_driver, port); |
@@ -1403,7 +1710,7 @@ mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) | |||
1403 | static int | 1710 | static int |
1404 | mpc52xx_uart_of_resume(struct platform_device *op) | 1711 | mpc52xx_uart_of_resume(struct platform_device *op) |
1405 | { | 1712 | { |
1406 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1713 | struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); |
1407 | 1714 | ||
1408 | if (port) | 1715 | if (port) |
1409 | uart_resume_port(&mpc52xx_uart_driver, port); | 1716 | uart_resume_port(&mpc52xx_uart_driver, port); |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 39c7ea4cb14f..2caf9c6f6149 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -204,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) | |||
204 | 204 | ||
205 | info->type = port_type; | 205 | info->type = port_type; |
206 | info->line = ret; | 206 | info->line = ret; |
207 | dev_set_drvdata(&ofdev->dev, info); | 207 | platform_set_drvdata(ofdev, info); |
208 | return 0; | 208 | return 0; |
209 | out: | 209 | out: |
210 | kfree(info); | 210 | kfree(info); |
@@ -217,7 +217,7 @@ out: | |||
217 | */ | 217 | */ |
218 | static int of_platform_serial_remove(struct platform_device *ofdev) | 218 | static int of_platform_serial_remove(struct platform_device *ofdev) |
219 | { | 219 | { |
220 | struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); | 220 | struct of_serial_info *info = platform_get_drvdata(ofdev); |
221 | switch (info->type) { | 221 | switch (info->type) { |
222 | #ifdef CONFIG_SERIAL_8250 | 222 | #ifdef CONFIG_SERIAL_8250 |
223 | case PORT_8250 ... PORT_MAX_8250: | 223 | case PORT_8250 ... PORT_MAX_8250: |
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index f0b9f6b52b32..156b5aaed95b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -161,6 +161,7 @@ struct uart_omap_port { | |||
161 | u32 calc_latency; | 161 | u32 calc_latency; |
162 | struct work_struct qos_work; | 162 | struct work_struct qos_work; |
163 | struct pinctrl *pins; | 163 | struct pinctrl *pins; |
164 | bool is_suspending; | ||
164 | }; | 165 | }; |
165 | 166 | ||
166 | #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) | 167 | #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) |
@@ -1289,6 +1290,22 @@ static struct uart_driver serial_omap_reg = { | |||
1289 | }; | 1290 | }; |
1290 | 1291 | ||
1291 | #ifdef CONFIG_PM_SLEEP | 1292 | #ifdef CONFIG_PM_SLEEP |
1293 | static int serial_omap_prepare(struct device *dev) | ||
1294 | { | ||
1295 | struct uart_omap_port *up = dev_get_drvdata(dev); | ||
1296 | |||
1297 | up->is_suspending = true; | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | static void serial_omap_complete(struct device *dev) | ||
1303 | { | ||
1304 | struct uart_omap_port *up = dev_get_drvdata(dev); | ||
1305 | |||
1306 | up->is_suspending = false; | ||
1307 | } | ||
1308 | |||
1292 | static int serial_omap_suspend(struct device *dev) | 1309 | static int serial_omap_suspend(struct device *dev) |
1293 | { | 1310 | { |
1294 | struct uart_omap_port *up = dev_get_drvdata(dev); | 1311 | struct uart_omap_port *up = dev_get_drvdata(dev); |
@@ -1307,7 +1324,10 @@ static int serial_omap_resume(struct device *dev) | |||
1307 | 1324 | ||
1308 | return 0; | 1325 | return 0; |
1309 | } | 1326 | } |
1310 | #endif | 1327 | #else |
1328 | #define serial_omap_prepare NULL | ||
1329 | #define serial_omap_complete NULL | ||
1330 | #endif /* CONFIG_PM_SLEEP */ | ||
1311 | 1331 | ||
1312 | static void omap_serial_fill_features_erratas(struct uart_omap_port *up) | 1332 | static void omap_serial_fill_features_erratas(struct uart_omap_port *up) |
1313 | { | 1333 | { |
@@ -1596,6 +1616,16 @@ static int serial_omap_runtime_suspend(struct device *dev) | |||
1596 | if (!up) | 1616 | if (!up) |
1597 | return -EINVAL; | 1617 | return -EINVAL; |
1598 | 1618 | ||
1619 | /* | ||
1620 | * When using 'no_console_suspend', the console UART must not be | ||
1621 | * suspended. Since driver suspend is managed by runtime suspend, | ||
1622 | * preventing runtime suspend (by returning error) will keep device | ||
1623 | * active during suspend. | ||
1624 | */ | ||
1625 | if (up->is_suspending && !console_suspend_enabled && | ||
1626 | uart_console(&up->port)) | ||
1627 | return -EBUSY; | ||
1628 | |||
1599 | if (!pdata) | 1629 | if (!pdata) |
1600 | return 0; | 1630 | return 0; |
1601 | 1631 | ||
@@ -1643,6 +1673,8 @@ static const struct dev_pm_ops serial_omap_dev_pm_ops = { | |||
1643 | SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume) | 1673 | SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume) |
1644 | SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend, | 1674 | SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend, |
1645 | serial_omap_runtime_resume, NULL) | 1675 | serial_omap_runtime_resume, NULL) |
1676 | .prepare = serial_omap_prepare, | ||
1677 | .complete = serial_omap_complete, | ||
1646 | }; | 1678 | }; |
1647 | 1679 | ||
1648 | #if defined(CONFIG_OF) | 1680 | #if defined(CONFIG_OF) |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 0c8a9fa2be6c..81ebc86a9e23 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -1811,7 +1811,13 @@ static int __init s3c24xx_serial_modinit(void) | |||
1811 | return ret; | 1811 | return ret; |
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | return platform_driver_register(&samsung_serial_driver); | 1814 | ret = platform_driver_register(&samsung_serial_driver); |
1815 | if (ret < 0) { | ||
1816 | pr_err("Failed to register platform driver\n"); | ||
1817 | uart_unregister_driver(&s3c24xx_uart_drv); | ||
1818 | } | ||
1819 | |||
1820 | return ret; | ||
1815 | } | 1821 | } |
1816 | 1822 | ||
1817 | static void __exit s3c24xx_serial_modexit(void) | 1823 | static void __exit s3c24xx_serial_modexit(void) |
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c index c9735680762d..4b1434d53e9d 100644 --- a/drivers/tty/serial/sc26xx.c +++ b/drivers/tty/serial/sc26xx.c | |||
@@ -696,7 +696,7 @@ static int sc26xx_probe(struct platform_device *dev) | |||
696 | if (err) | 696 | if (err) |
697 | goto out_remove_ports; | 697 | goto out_remove_ports; |
698 | 698 | ||
699 | dev_set_drvdata(&dev->dev, up); | 699 | platform_set_drvdata(dev, up); |
700 | return 0; | 700 | return 0; |
701 | 701 | ||
702 | out_remove_ports: | 702 | out_remove_ports: |
@@ -716,7 +716,7 @@ out_free_port: | |||
716 | 716 | ||
717 | static int __exit sc26xx_driver_remove(struct platform_device *dev) | 717 | static int __exit sc26xx_driver_remove(struct platform_device *dev) |
718 | { | 718 | { |
719 | struct uart_sc26xx_port *up = dev_get_drvdata(&dev->dev); | 719 | struct uart_sc26xx_port *up = platform_get_drvdata(dev); |
720 | 720 | ||
721 | free_irq(up->port[0].irq, up); | 721 | free_irq(up->port[0].irq, up); |
722 | 722 | ||
@@ -728,7 +728,6 @@ static int __exit sc26xx_driver_remove(struct platform_device *dev) | |||
728 | kfree(up); | 728 | kfree(up); |
729 | sc26xx_port = NULL; | 729 | sc26xx_port = NULL; |
730 | 730 | ||
731 | dev_set_drvdata(&dev->dev, NULL); | ||
732 | return 0; | 731 | return 0; |
733 | } | 732 | } |
734 | 733 | ||
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index f87dbfd32770..28cdd2829139 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -50,12 +50,6 @@ static struct lock_class_key port_lock_key; | |||
50 | 50 | ||
51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
52 | 52 | ||
53 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | ||
54 | #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) | ||
55 | #else | ||
56 | #define uart_console(port) (0) | ||
57 | #endif | ||
58 | |||
59 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | 53 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
60 | struct ktermios *old_termios); | 54 | struct ktermios *old_termios); |
61 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 55 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); |
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 03465b673945..1fd564b8194b 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c | |||
@@ -687,9 +687,10 @@ int sirfsoc_uart_probe(struct platform_device *pdev) | |||
687 | 687 | ||
688 | if (sirfport->hw_flow_ctrl) { | 688 | if (sirfport->hw_flow_ctrl) { |
689 | sirfport->p = pinctrl_get_select_default(&pdev->dev); | 689 | sirfport->p = pinctrl_get_select_default(&pdev->dev); |
690 | ret = IS_ERR(sirfport->p); | 690 | if (IS_ERR(sirfport->p)) { |
691 | if (ret) | 691 | ret = PTR_ERR(sirfport->p); |
692 | goto err; | 692 | goto err; |
693 | } | ||
693 | } | 694 | } |
694 | 695 | ||
695 | sirfport->clk = clk_get(&pdev->dev, NULL); | 696 | sirfport->clk = clk_get(&pdev->dev, NULL); |
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index ba60708053e0..cf86e729532b 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c | |||
@@ -577,7 +577,7 @@ static int hv_probe(struct platform_device *op) | |||
577 | if (err) | 577 | if (err) |
578 | goto out_remove_port; | 578 | goto out_remove_port; |
579 | 579 | ||
580 | dev_set_drvdata(&op->dev, port); | 580 | platform_set_drvdata(op, port); |
581 | 581 | ||
582 | return 0; | 582 | return 0; |
583 | 583 | ||
@@ -601,7 +601,7 @@ out_free_port: | |||
601 | 601 | ||
602 | static int hv_remove(struct platform_device *dev) | 602 | static int hv_remove(struct platform_device *dev) |
603 | { | 603 | { |
604 | struct uart_port *port = dev_get_drvdata(&dev->dev); | 604 | struct uart_port *port = platform_get_drvdata(dev); |
605 | 605 | ||
606 | free_irq(port->irq, port); | 606 | free_irq(port->irq, port); |
607 | 607 | ||
@@ -612,8 +612,6 @@ static int hv_remove(struct platform_device *dev) | |||
612 | kfree(port); | 612 | kfree(port); |
613 | sunhv_port = NULL; | 613 | sunhv_port = NULL; |
614 | 614 | ||
615 | dev_set_drvdata(&dev->dev, NULL); | ||
616 | |||
617 | return 0; | 615 | return 0; |
618 | } | 616 | } |
619 | 617 | ||
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index a422c8b55a47..5d6136b2a04a 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c | |||
@@ -1037,7 +1037,7 @@ static int sab_probe(struct platform_device *op) | |||
1037 | if (err) | 1037 | if (err) |
1038 | goto out3; | 1038 | goto out3; |
1039 | 1039 | ||
1040 | dev_set_drvdata(&op->dev, &up[0]); | 1040 | platform_set_drvdata(op, &up[0]); |
1041 | 1041 | ||
1042 | inst++; | 1042 | inst++; |
1043 | 1043 | ||
@@ -1059,7 +1059,7 @@ out: | |||
1059 | 1059 | ||
1060 | static int sab_remove(struct platform_device *op) | 1060 | static int sab_remove(struct platform_device *op) |
1061 | { | 1061 | { |
1062 | struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); | 1062 | struct uart_sunsab_port *up = platform_get_drvdata(op); |
1063 | 1063 | ||
1064 | uart_remove_one_port(&sunsab_reg, &up[1].port); | 1064 | uart_remove_one_port(&sunsab_reg, &up[1].port); |
1065 | uart_remove_one_port(&sunsab_reg, &up[0].port); | 1065 | uart_remove_one_port(&sunsab_reg, &up[0].port); |
@@ -1070,8 +1070,6 @@ static int sab_remove(struct platform_device *op) | |||
1070 | up[0].port.membase, | 1070 | up[0].port.membase, |
1071 | sizeof(union sab82532_async_regs)); | 1071 | sizeof(union sab82532_async_regs)); |
1072 | 1072 | ||
1073 | dev_set_drvdata(&op->dev, NULL); | ||
1074 | |||
1075 | return 0; | 1073 | return 0; |
1076 | } | 1074 | } |
1077 | 1075 | ||
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 0d8465728473..699cc1b5f6aa 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c | |||
@@ -1454,7 +1454,7 @@ static int su_probe(struct platform_device *op) | |||
1454 | kfree(up); | 1454 | kfree(up); |
1455 | return err; | 1455 | return err; |
1456 | } | 1456 | } |
1457 | dev_set_drvdata(&op->dev, up); | 1457 | platform_set_drvdata(op, up); |
1458 | 1458 | ||
1459 | nr_inst++; | 1459 | nr_inst++; |
1460 | 1460 | ||
@@ -1483,7 +1483,7 @@ static int su_probe(struct platform_device *op) | |||
1483 | if (err) | 1483 | if (err) |
1484 | goto out_unmap; | 1484 | goto out_unmap; |
1485 | 1485 | ||
1486 | dev_set_drvdata(&op->dev, up); | 1486 | platform_set_drvdata(op, up); |
1487 | 1487 | ||
1488 | nr_inst++; | 1488 | nr_inst++; |
1489 | 1489 | ||
@@ -1496,7 +1496,7 @@ out_unmap: | |||
1496 | 1496 | ||
1497 | static int su_remove(struct platform_device *op) | 1497 | static int su_remove(struct platform_device *op) |
1498 | { | 1498 | { |
1499 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); | 1499 | struct uart_sunsu_port *up = platform_get_drvdata(op); |
1500 | bool kbdms = false; | 1500 | bool kbdms = false; |
1501 | 1501 | ||
1502 | if (up->su_type == SU_PORT_MS || | 1502 | if (up->su_type == SU_PORT_MS || |
@@ -1516,8 +1516,6 @@ static int su_remove(struct platform_device *op) | |||
1516 | if (kbdms) | 1516 | if (kbdms) |
1517 | kfree(up); | 1517 | kfree(up); |
1518 | 1518 | ||
1519 | dev_set_drvdata(&op->dev, NULL); | ||
1520 | |||
1521 | return 0; | 1519 | return 0; |
1522 | } | 1520 | } |
1523 | 1521 | ||
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 813ef8eb8eff..135a15203532 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c | |||
@@ -1495,7 +1495,7 @@ static int zs_probe(struct platform_device *op) | |||
1495 | kbm_inst++; | 1495 | kbm_inst++; |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | dev_set_drvdata(&op->dev, &up[0]); | 1498 | platform_set_drvdata(op, &up[0]); |
1499 | 1499 | ||
1500 | return 0; | 1500 | return 0; |
1501 | } | 1501 | } |
@@ -1512,7 +1512,7 @@ static void zs_remove_one(struct uart_sunzilog_port *up) | |||
1512 | 1512 | ||
1513 | static int zs_remove(struct platform_device *op) | 1513 | static int zs_remove(struct platform_device *op) |
1514 | { | 1514 | { |
1515 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); | 1515 | struct uart_sunzilog_port *up = platform_get_drvdata(op); |
1516 | struct zilog_layout __iomem *regs; | 1516 | struct zilog_layout __iomem *regs; |
1517 | 1517 | ||
1518 | zs_remove_one(&up[0]); | 1518 | zs_remove_one(&up[0]); |
@@ -1521,8 +1521,6 @@ static int zs_remove(struct platform_device *op) | |||
1521 | regs = sunzilog_chip_regs[up[0].port.line / 2]; | 1521 | regs = sunzilog_chip_regs[up[0].port.line / 2]; |
1522 | of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout)); | 1522 | of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout)); |
1523 | 1523 | ||
1524 | dev_set_drvdata(&op->dev, NULL); | ||
1525 | |||
1526 | return 0; | 1524 | return 0; |
1527 | } | 1525 | } |
1528 | 1526 | ||
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 7355303dad99..88317482b81f 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c | |||
@@ -1451,7 +1451,7 @@ static int ucc_uart_probe(struct platform_device *ofdev) | |||
1451 | goto out_np; | 1451 | goto out_np; |
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | dev_set_drvdata(&ofdev->dev, qe_port); | 1454 | platform_set_drvdata(ofdev, qe_port); |
1455 | 1455 | ||
1456 | dev_info(&ofdev->dev, "UCC%u assigned to /dev/ttyQE%u\n", | 1456 | dev_info(&ofdev->dev, "UCC%u assigned to /dev/ttyQE%u\n", |
1457 | qe_port->ucc_num + 1, qe_port->port.line); | 1457 | qe_port->ucc_num + 1, qe_port->port.line); |
@@ -1471,13 +1471,12 @@ out_free: | |||
1471 | 1471 | ||
1472 | static int ucc_uart_remove(struct platform_device *ofdev) | 1472 | static int ucc_uart_remove(struct platform_device *ofdev) |
1473 | { | 1473 | { |
1474 | struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); | 1474 | struct uart_qe_port *qe_port = platform_get_drvdata(ofdev); |
1475 | 1475 | ||
1476 | dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line); | 1476 | dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line); |
1477 | 1477 | ||
1478 | uart_remove_one_port(&ucc_uart_driver, &qe_port->port); | 1478 | uart_remove_one_port(&ucc_uart_driver, &qe_port->port); |
1479 | 1479 | ||
1480 | dev_set_drvdata(&ofdev->dev, NULL); | ||
1481 | kfree(qe_port); | 1480 | kfree(qe_port); |
1482 | 1481 | ||
1483 | return 0; | 1482 | return 0; |
@@ -1518,9 +1517,11 @@ static int __init ucc_uart_init(void) | |||
1518 | } | 1517 | } |
1519 | 1518 | ||
1520 | ret = platform_driver_register(&ucc_uart_of_driver); | 1519 | ret = platform_driver_register(&ucc_uart_of_driver); |
1521 | if (ret) | 1520 | if (ret) { |
1522 | printk(KERN_ERR | 1521 | printk(KERN_ERR |
1523 | "ucc-uart: could not register platform driver\n"); | 1522 | "ucc-uart: could not register platform driver\n"); |
1523 | uart_unregister_driver(&ucc_uart_driver); | ||
1524 | } | ||
1524 | 1525 | ||
1525 | return ret; | 1526 | return ret; |
1526 | } | 1527 | } |
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 1a8bc2275ea4..48af43de3467 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c | |||
@@ -648,7 +648,7 @@ static struct platform_driver vt8500_platform_driver = { | |||
648 | .driver = { | 648 | .driver = { |
649 | .name = "vt8500_serial", | 649 | .name = "vt8500_serial", |
650 | .owner = THIS_MODULE, | 650 | .owner = THIS_MODULE, |
651 | .of_match_table = of_match_ptr(wmt_dt_ids), | 651 | .of_match_table = wmt_dt_ids, |
652 | }, | 652 | }, |
653 | }; | 653 | }; |
654 | 654 | ||
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 4e5c77834c50..6c9174530422 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -974,12 +974,11 @@ static int xuartps_probe(struct platform_device *pdev) | |||
974 | port->dev = &pdev->dev; | 974 | port->dev = &pdev->dev; |
975 | port->uartclk = clk_get_rate(clk); | 975 | port->uartclk = clk_get_rate(clk); |
976 | port->private_data = clk; | 976 | port->private_data = clk; |
977 | dev_set_drvdata(&pdev->dev, port); | 977 | platform_set_drvdata(pdev, port); |
978 | rc = uart_add_one_port(&xuartps_uart_driver, port); | 978 | rc = uart_add_one_port(&xuartps_uart_driver, port); |
979 | if (rc) { | 979 | if (rc) { |
980 | dev_err(&pdev->dev, | 980 | dev_err(&pdev->dev, |
981 | "uart_add_one_port() failed; err=%i\n", rc); | 981 | "uart_add_one_port() failed; err=%i\n", rc); |
982 | dev_set_drvdata(&pdev->dev, NULL); | ||
983 | return rc; | 982 | return rc; |
984 | } | 983 | } |
985 | return 0; | 984 | return 0; |
@@ -994,46 +993,17 @@ static int xuartps_probe(struct platform_device *pdev) | |||
994 | **/ | 993 | **/ |
995 | static int xuartps_remove(struct platform_device *pdev) | 994 | static int xuartps_remove(struct platform_device *pdev) |
996 | { | 995 | { |
997 | struct uart_port *port = dev_get_drvdata(&pdev->dev); | 996 | struct uart_port *port = platform_get_drvdata(pdev); |
998 | struct clk *clk = port->private_data; | 997 | struct clk *clk = port->private_data; |
999 | int rc; | 998 | int rc; |
1000 | 999 | ||
1001 | /* Remove the xuartps port from the serial core */ | 1000 | /* Remove the xuartps port from the serial core */ |
1002 | rc = uart_remove_one_port(&xuartps_uart_driver, port); | 1001 | rc = uart_remove_one_port(&xuartps_uart_driver, port); |
1003 | dev_set_drvdata(&pdev->dev, NULL); | ||
1004 | port->mapbase = 0; | 1002 | port->mapbase = 0; |
1005 | clk_disable_unprepare(clk); | 1003 | clk_disable_unprepare(clk); |
1006 | return rc; | 1004 | return rc; |
1007 | } | 1005 | } |
1008 | 1006 | ||
1009 | /** | ||
1010 | * xuartps_suspend - suspend event | ||
1011 | * @pdev: Pointer to the platform device structure | ||
1012 | * @state: State of the device | ||
1013 | * | ||
1014 | * Returns 0 | ||
1015 | **/ | ||
1016 | static int xuartps_suspend(struct platform_device *pdev, pm_message_t state) | ||
1017 | { | ||
1018 | /* Call the API provided in serial_core.c file which handles | ||
1019 | * the suspend. | ||
1020 | */ | ||
1021 | uart_suspend_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); | ||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | /** | ||
1026 | * xuartps_resume - Resume after a previous suspend | ||
1027 | * @pdev: Pointer to the platform device structure | ||
1028 | * | ||
1029 | * Returns 0 | ||
1030 | **/ | ||
1031 | static int xuartps_resume(struct platform_device *pdev) | ||
1032 | { | ||
1033 | uart_resume_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | /* Match table for of_platform binding */ | 1007 | /* Match table for of_platform binding */ |
1038 | static struct of_device_id xuartps_of_match[] = { | 1008 | static struct of_device_id xuartps_of_match[] = { |
1039 | { .compatible = "xlnx,xuartps", }, | 1009 | { .compatible = "xlnx,xuartps", }, |
@@ -1044,8 +1014,6 @@ MODULE_DEVICE_TABLE(of, xuartps_of_match); | |||
1044 | static struct platform_driver xuartps_platform_driver = { | 1014 | static struct platform_driver xuartps_platform_driver = { |
1045 | .probe = xuartps_probe, /* Probe method */ | 1015 | .probe = xuartps_probe, /* Probe method */ |
1046 | .remove = xuartps_remove, /* Detach method */ | 1016 | .remove = xuartps_remove, /* Detach method */ |
1047 | .suspend = xuartps_suspend, /* Suspend */ | ||
1048 | .resume = xuartps_resume, /* Resume after a suspend */ | ||
1049 | .driver = { | 1017 | .driver = { |
1050 | .owner = THIS_MODULE, | 1018 | .owner = THIS_MODULE, |
1051 | .name = XUARTPS_NAME, /* Driver name */ | 1019 | .name = XUARTPS_NAME, /* Driver name */ |
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b51c15408ff3..5f68f2cfdfd0 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -932,7 +932,7 @@ static int sysrq_reset_seq_param_set(const char *buffer, | |||
932 | unsigned long val; | 932 | unsigned long val; |
933 | int error; | 933 | int error; |
934 | 934 | ||
935 | error = strict_strtoul(buffer, 0, &val); | 935 | error = kstrtoul(buffer, 0, &val); |
936 | if (error < 0) | 936 | if (error < 0) |
937 | return error; | 937 | return error; |
938 | 938 | ||
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c new file mode 100644 index 000000000000..22fad8ad5ac2 --- /dev/null +++ b/drivers/tty/tty_ldsem.c | |||
@@ -0,0 +1,453 @@ | |||
1 | /* | ||
2 | * Ldisc rw semaphore | ||
3 | * | ||
4 | * The ldisc semaphore is semantically a rw_semaphore but which enforces | ||
5 | * an alternate policy, namely: | ||
6 | * 1) Supports lock wait timeouts | ||
7 | * 2) Write waiter has priority | ||
8 | * 3) Downgrading is not supported | ||
9 | * | ||
10 | * Implementation notes: | ||
11 | * 1) Upper half of semaphore count is a wait count (differs from rwsem | ||
12 | * in that rwsem normalizes the upper half to the wait bias) | ||
13 | * 2) Lacks overflow checking | ||
14 | * | ||
15 | * The generic counting was copied and modified from include/asm-generic/rwsem.h | ||
16 | * by Paul Mackerras <paulus@samba.org>. | ||
17 | * | ||
18 | * The scheduling policy was copied and modified from lib/rwsem.c | ||
19 | * Written by David Howells (dhowells@redhat.com). | ||
20 | * | ||
21 | * This implementation incorporates the write lock stealing work of | ||
22 | * Michel Lespinasse <walken@google.com>. | ||
23 | * | ||
24 | * Copyright (C) 2013 Peter Hurley <peter@hurleysoftware.com> | ||
25 | * | ||
26 | * This file may be redistributed under the terms of the GNU General Public | ||
27 | * License v2. | ||
28 | */ | ||
29 | |||
30 | #include <linux/list.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/atomic.h> | ||
33 | #include <linux/tty.h> | ||
34 | #include <linux/sched.h> | ||
35 | |||
36 | |||
37 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
38 | # define __acq(l, s, t, r, c, n, i) \ | ||
39 | lock_acquire(&(l)->dep_map, s, t, r, c, n, i) | ||
40 | # define __rel(l, n, i) \ | ||
41 | lock_release(&(l)->dep_map, n, i) | ||
42 | # ifdef CONFIG_PROVE_LOCKING | ||
43 | # define lockdep_acquire(l, s, t, i) __acq(l, s, t, 0, 2, NULL, i) | ||
44 | # define lockdep_acquire_nest(l, s, t, n, i) __acq(l, s, t, 0, 2, n, i) | ||
45 | # define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 1, 2, NULL, i) | ||
46 | # define lockdep_release(l, n, i) __rel(l, n, i) | ||
47 | # else | ||
48 | # define lockdep_acquire(l, s, t, i) __acq(l, s, t, 0, 1, NULL, i) | ||
49 | # define lockdep_acquire_nest(l, s, t, n, i) __acq(l, s, t, 0, 1, n, i) | ||
50 | # define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 1, 1, NULL, i) | ||
51 | # define lockdep_release(l, n, i) __rel(l, n, i) | ||
52 | # endif | ||
53 | #else | ||
54 | # define lockdep_acquire(l, s, t, i) do { } while (0) | ||
55 | # define lockdep_acquire_nest(l, s, t, n, i) do { } while (0) | ||
56 | # define lockdep_acquire_read(l, s, t, i) do { } while (0) | ||
57 | # define lockdep_release(l, n, i) do { } while (0) | ||
58 | #endif | ||
59 | |||
60 | #ifdef CONFIG_LOCK_STAT | ||
61 | # define lock_stat(_lock, stat) lock_##stat(&(_lock)->dep_map, _RET_IP_) | ||
62 | #else | ||
63 | # define lock_stat(_lock, stat) do { } while (0) | ||
64 | #endif | ||
65 | |||
66 | |||
67 | #if BITS_PER_LONG == 64 | ||
68 | # define LDSEM_ACTIVE_MASK 0xffffffffL | ||
69 | #else | ||
70 | # define LDSEM_ACTIVE_MASK 0x0000ffffL | ||
71 | #endif | ||
72 | |||
73 | #define LDSEM_UNLOCKED 0L | ||
74 | #define LDSEM_ACTIVE_BIAS 1L | ||
75 | #define LDSEM_WAIT_BIAS (-LDSEM_ACTIVE_MASK-1) | ||
76 | #define LDSEM_READ_BIAS LDSEM_ACTIVE_BIAS | ||
77 | #define LDSEM_WRITE_BIAS (LDSEM_WAIT_BIAS + LDSEM_ACTIVE_BIAS) | ||
78 | |||
79 | struct ldsem_waiter { | ||
80 | struct list_head list; | ||
81 | struct task_struct *task; | ||
82 | }; | ||
83 | |||
84 | static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem) | ||
85 | { | ||
86 | return atomic_long_add_return(delta, (atomic_long_t *)&sem->count); | ||
87 | } | ||
88 | |||
89 | static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem) | ||
90 | { | ||
91 | long tmp = *old; | ||
92 | *old = atomic_long_cmpxchg(&sem->count, *old, new); | ||
93 | return *old == tmp; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Initialize an ldsem: | ||
98 | */ | ||
99 | void __init_ldsem(struct ld_semaphore *sem, const char *name, | ||
100 | struct lock_class_key *key) | ||
101 | { | ||
102 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
103 | /* | ||
104 | * Make sure we are not reinitializing a held semaphore: | ||
105 | */ | ||
106 | debug_check_no_locks_freed((void *)sem, sizeof(*sem)); | ||
107 | lockdep_init_map(&sem->dep_map, name, key, 0); | ||
108 | #endif | ||
109 | sem->count = LDSEM_UNLOCKED; | ||
110 | sem->wait_readers = 0; | ||
111 | raw_spin_lock_init(&sem->wait_lock); | ||
112 | INIT_LIST_HEAD(&sem->read_wait); | ||
113 | INIT_LIST_HEAD(&sem->write_wait); | ||
114 | } | ||
115 | |||
116 | static void __ldsem_wake_readers(struct ld_semaphore *sem) | ||
117 | { | ||
118 | struct ldsem_waiter *waiter, *next; | ||
119 | struct task_struct *tsk; | ||
120 | long adjust, count; | ||
121 | |||
122 | /* Try to grant read locks to all readers on the read wait list. | ||
123 | * Note the 'active part' of the count is incremented by | ||
124 | * the number of readers before waking any processes up. | ||
125 | */ | ||
126 | adjust = sem->wait_readers * (LDSEM_ACTIVE_BIAS - LDSEM_WAIT_BIAS); | ||
127 | count = ldsem_atomic_update(adjust, sem); | ||
128 | do { | ||
129 | if (count > 0) | ||
130 | break; | ||
131 | if (ldsem_cmpxchg(&count, count - adjust, sem)) | ||
132 | return; | ||
133 | } while (1); | ||
134 | |||
135 | list_for_each_entry_safe(waiter, next, &sem->read_wait, list) { | ||
136 | tsk = waiter->task; | ||
137 | smp_mb(); | ||
138 | waiter->task = NULL; | ||
139 | wake_up_process(tsk); | ||
140 | put_task_struct(tsk); | ||
141 | } | ||
142 | INIT_LIST_HEAD(&sem->read_wait); | ||
143 | sem->wait_readers = 0; | ||
144 | } | ||
145 | |||
146 | static inline int writer_trylock(struct ld_semaphore *sem) | ||
147 | { | ||
148 | /* only wake this writer if the active part of the count can be | ||
149 | * transitioned from 0 -> 1 | ||
150 | */ | ||
151 | long count = ldsem_atomic_update(LDSEM_ACTIVE_BIAS, sem); | ||
152 | do { | ||
153 | if ((count & LDSEM_ACTIVE_MASK) == LDSEM_ACTIVE_BIAS) | ||
154 | return 1; | ||
155 | if (ldsem_cmpxchg(&count, count - LDSEM_ACTIVE_BIAS, sem)) | ||
156 | return 0; | ||
157 | } while (1); | ||
158 | } | ||
159 | |||
160 | static void __ldsem_wake_writer(struct ld_semaphore *sem) | ||
161 | { | ||
162 | struct ldsem_waiter *waiter; | ||
163 | |||
164 | waiter = list_entry(sem->write_wait.next, struct ldsem_waiter, list); | ||
165 | wake_up_process(waiter->task); | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * handle the lock release when processes blocked on it that can now run | ||
170 | * - if we come here from up_xxxx(), then: | ||
171 | * - the 'active part' of count (&0x0000ffff) reached 0 (but may have changed) | ||
172 | * - the 'waiting part' of count (&0xffff0000) is -ve (and will still be so) | ||
173 | * - the spinlock must be held by the caller | ||
174 | * - woken process blocks are discarded from the list after having task zeroed | ||
175 | */ | ||
176 | static void __ldsem_wake(struct ld_semaphore *sem) | ||
177 | { | ||
178 | if (!list_empty(&sem->write_wait)) | ||
179 | __ldsem_wake_writer(sem); | ||
180 | else if (!list_empty(&sem->read_wait)) | ||
181 | __ldsem_wake_readers(sem); | ||
182 | } | ||
183 | |||
184 | static void ldsem_wake(struct ld_semaphore *sem) | ||
185 | { | ||
186 | unsigned long flags; | ||
187 | |||
188 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | ||
189 | __ldsem_wake(sem); | ||
190 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * wait for the read lock to be granted | ||
195 | */ | ||
196 | static struct ld_semaphore __sched * | ||
197 | down_read_failed(struct ld_semaphore *sem, long count, long timeout) | ||
198 | { | ||
199 | struct ldsem_waiter waiter; | ||
200 | struct task_struct *tsk = current; | ||
201 | long adjust = -LDSEM_ACTIVE_BIAS + LDSEM_WAIT_BIAS; | ||
202 | |||
203 | /* set up my own style of waitqueue */ | ||
204 | raw_spin_lock_irq(&sem->wait_lock); | ||
205 | |||
206 | /* Try to reverse the lock attempt but if the count has changed | ||
207 | * so that reversing fails, check if there are are no waiters, | ||
208 | * and early-out if not */ | ||
209 | do { | ||
210 | if (ldsem_cmpxchg(&count, count + adjust, sem)) | ||
211 | break; | ||
212 | if (count > 0) { | ||
213 | raw_spin_unlock_irq(&sem->wait_lock); | ||
214 | return sem; | ||
215 | } | ||
216 | } while (1); | ||
217 | |||
218 | list_add_tail(&waiter.list, &sem->read_wait); | ||
219 | sem->wait_readers++; | ||
220 | |||
221 | waiter.task = tsk; | ||
222 | get_task_struct(tsk); | ||
223 | |||
224 | /* if there are no active locks, wake the new lock owner(s) */ | ||
225 | if ((count & LDSEM_ACTIVE_MASK) == 0) | ||
226 | __ldsem_wake(sem); | ||
227 | |||
228 | raw_spin_unlock_irq(&sem->wait_lock); | ||
229 | |||
230 | /* wait to be given the lock */ | ||
231 | for (;;) { | ||
232 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
233 | |||
234 | if (!waiter.task) | ||
235 | break; | ||
236 | if (!timeout) | ||
237 | break; | ||
238 | timeout = schedule_timeout(timeout); | ||
239 | } | ||
240 | |||
241 | __set_task_state(tsk, TASK_RUNNING); | ||
242 | |||
243 | if (!timeout) { | ||
244 | /* lock timed out but check if this task was just | ||
245 | * granted lock ownership - if so, pretend there | ||
246 | * was no timeout; otherwise, cleanup lock wait */ | ||
247 | raw_spin_lock_irq(&sem->wait_lock); | ||
248 | if (waiter.task) { | ||
249 | ldsem_atomic_update(-LDSEM_WAIT_BIAS, sem); | ||
250 | list_del(&waiter.list); | ||
251 | raw_spin_unlock_irq(&sem->wait_lock); | ||
252 | put_task_struct(waiter.task); | ||
253 | return NULL; | ||
254 | } | ||
255 | raw_spin_unlock_irq(&sem->wait_lock); | ||
256 | } | ||
257 | |||
258 | return sem; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * wait for the write lock to be granted | ||
263 | */ | ||
264 | static struct ld_semaphore __sched * | ||
265 | down_write_failed(struct ld_semaphore *sem, long count, long timeout) | ||
266 | { | ||
267 | struct ldsem_waiter waiter; | ||
268 | struct task_struct *tsk = current; | ||
269 | long adjust = -LDSEM_ACTIVE_BIAS; | ||
270 | int locked = 0; | ||
271 | |||
272 | /* set up my own style of waitqueue */ | ||
273 | raw_spin_lock_irq(&sem->wait_lock); | ||
274 | |||
275 | /* Try to reverse the lock attempt but if the count has changed | ||
276 | * so that reversing fails, check if the lock is now owned, | ||
277 | * and early-out if so */ | ||
278 | do { | ||
279 | if (ldsem_cmpxchg(&count, count + adjust, sem)) | ||
280 | break; | ||
281 | if ((count & LDSEM_ACTIVE_MASK) == LDSEM_ACTIVE_BIAS) { | ||
282 | raw_spin_unlock_irq(&sem->wait_lock); | ||
283 | return sem; | ||
284 | } | ||
285 | } while (1); | ||
286 | |||
287 | list_add_tail(&waiter.list, &sem->write_wait); | ||
288 | |||
289 | waiter.task = tsk; | ||
290 | |||
291 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
292 | for (;;) { | ||
293 | if (!timeout) | ||
294 | break; | ||
295 | raw_spin_unlock_irq(&sem->wait_lock); | ||
296 | timeout = schedule_timeout(timeout); | ||
297 | raw_spin_lock_irq(&sem->wait_lock); | ||
298 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
299 | if ((locked = writer_trylock(sem))) | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | if (!locked) | ||
304 | ldsem_atomic_update(-LDSEM_WAIT_BIAS, sem); | ||
305 | list_del(&waiter.list); | ||
306 | raw_spin_unlock_irq(&sem->wait_lock); | ||
307 | |||
308 | __set_task_state(tsk, TASK_RUNNING); | ||
309 | |||
310 | /* lock wait may have timed out */ | ||
311 | if (!locked) | ||
312 | return NULL; | ||
313 | return sem; | ||
314 | } | ||
315 | |||
316 | |||
317 | |||
318 | static inline int __ldsem_down_read_nested(struct ld_semaphore *sem, | ||
319 | int subclass, long timeout) | ||
320 | { | ||
321 | long count; | ||
322 | |||
323 | lockdep_acquire_read(sem, subclass, 0, _RET_IP_); | ||
324 | |||
325 | count = ldsem_atomic_update(LDSEM_READ_BIAS, sem); | ||
326 | if (count <= 0) { | ||
327 | lock_stat(sem, contended); | ||
328 | if (!down_read_failed(sem, count, timeout)) { | ||
329 | lockdep_release(sem, 1, _RET_IP_); | ||
330 | return 0; | ||
331 | } | ||
332 | } | ||
333 | lock_stat(sem, acquired); | ||
334 | return 1; | ||
335 | } | ||
336 | |||
337 | static inline int __ldsem_down_write_nested(struct ld_semaphore *sem, | ||
338 | int subclass, long timeout) | ||
339 | { | ||
340 | long count; | ||
341 | |||
342 | lockdep_acquire(sem, subclass, 0, _RET_IP_); | ||
343 | |||
344 | count = ldsem_atomic_update(LDSEM_WRITE_BIAS, sem); | ||
345 | if ((count & LDSEM_ACTIVE_MASK) != LDSEM_ACTIVE_BIAS) { | ||
346 | lock_stat(sem, contended); | ||
347 | if (!down_write_failed(sem, count, timeout)) { | ||
348 | lockdep_release(sem, 1, _RET_IP_); | ||
349 | return 0; | ||
350 | } | ||
351 | } | ||
352 | lock_stat(sem, acquired); | ||
353 | return 1; | ||
354 | } | ||
355 | |||
356 | |||
357 | /* | ||
358 | * lock for reading -- returns 1 if successful, 0 if timed out | ||
359 | */ | ||
360 | int __sched ldsem_down_read(struct ld_semaphore *sem, long timeout) | ||
361 | { | ||
362 | might_sleep(); | ||
363 | return __ldsem_down_read_nested(sem, 0, timeout); | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * trylock for reading -- returns 1 if successful, 0 if contention | ||
368 | */ | ||
369 | int ldsem_down_read_trylock(struct ld_semaphore *sem) | ||
370 | { | ||
371 | long count = sem->count; | ||
372 | |||
373 | while (count >= 0) { | ||
374 | if (ldsem_cmpxchg(&count, count + LDSEM_READ_BIAS, sem)) { | ||
375 | lockdep_acquire_read(sem, 0, 1, _RET_IP_); | ||
376 | lock_stat(sem, acquired); | ||
377 | return 1; | ||
378 | } | ||
379 | } | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * lock for writing -- returns 1 if successful, 0 if timed out | ||
385 | */ | ||
386 | int __sched ldsem_down_write(struct ld_semaphore *sem, long timeout) | ||
387 | { | ||
388 | might_sleep(); | ||
389 | return __ldsem_down_write_nested(sem, 0, timeout); | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * trylock for writing -- returns 1 if successful, 0 if contention | ||
394 | */ | ||
395 | int ldsem_down_write_trylock(struct ld_semaphore *sem) | ||
396 | { | ||
397 | long count = sem->count; | ||
398 | |||
399 | while ((count & LDSEM_ACTIVE_MASK) == 0) { | ||
400 | if (ldsem_cmpxchg(&count, count + LDSEM_WRITE_BIAS, sem)) { | ||
401 | lockdep_acquire(sem, 0, 1, _RET_IP_); | ||
402 | lock_stat(sem, acquired); | ||
403 | return 1; | ||
404 | } | ||
405 | } | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * release a read lock | ||
411 | */ | ||
412 | void ldsem_up_read(struct ld_semaphore *sem) | ||
413 | { | ||
414 | long count; | ||
415 | |||
416 | lockdep_release(sem, 1, _RET_IP_); | ||
417 | |||
418 | count = ldsem_atomic_update(-LDSEM_READ_BIAS, sem); | ||
419 | if (count < 0 && (count & LDSEM_ACTIVE_MASK) == 0) | ||
420 | ldsem_wake(sem); | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * release a write lock | ||
425 | */ | ||
426 | void ldsem_up_write(struct ld_semaphore *sem) | ||
427 | { | ||
428 | long count; | ||
429 | |||
430 | lockdep_release(sem, 1, _RET_IP_); | ||
431 | |||
432 | count = ldsem_atomic_update(-LDSEM_WRITE_BIAS, sem); | ||
433 | if (count < 0) | ||
434 | ldsem_wake(sem); | ||
435 | } | ||
436 | |||
437 | |||
438 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
439 | |||
440 | int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass, long timeout) | ||
441 | { | ||
442 | might_sleep(); | ||
443 | return __ldsem_down_read_nested(sem, subclass, timeout); | ||
444 | } | ||
445 | |||
446 | int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass, | ||
447 | long timeout) | ||
448 | { | ||
449 | might_sleep(); | ||
450 | return __ldsem_down_write_nested(sem, subclass, timeout); | ||
451 | } | ||
452 | |||
453 | #endif | ||
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 740202d8a5c4..c677829baa8b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -3086,17 +3086,6 @@ err: | |||
3086 | }; | 3086 | }; |
3087 | 3087 | ||
3088 | 3088 | ||
3089 | static int bind_con_driver(const struct consw *csw, int first, int last, | ||
3090 | int deflt) | ||
3091 | { | ||
3092 | int ret; | ||
3093 | |||
3094 | console_lock(); | ||
3095 | ret = do_bind_con_driver(csw, first, last, deflt); | ||
3096 | console_unlock(); | ||
3097 | return ret; | ||
3098 | } | ||
3099 | |||
3100 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING | 3089 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING |
3101 | static int con_is_graphics(const struct consw *csw, int first, int last) | 3090 | static int con_is_graphics(const struct consw *csw, int first, int last) |
3102 | { | 3091 | { |
@@ -3114,34 +3103,6 @@ static int con_is_graphics(const struct consw *csw, int first, int last) | |||
3114 | return retval; | 3103 | return retval; |
3115 | } | 3104 | } |
3116 | 3105 | ||
3117 | /** | ||
3118 | * unbind_con_driver - unbind a console driver | ||
3119 | * @csw: pointer to console driver to unregister | ||
3120 | * @first: first in range of consoles that @csw should be unbound from | ||
3121 | * @last: last in range of consoles that @csw should be unbound from | ||
3122 | * @deflt: should next bound console driver be default after @csw is unbound? | ||
3123 | * | ||
3124 | * To unbind a driver from all possible consoles, pass 0 as @first and | ||
3125 | * %MAX_NR_CONSOLES as @last. | ||
3126 | * | ||
3127 | * @deflt controls whether the console that ends up replacing @csw should be | ||
3128 | * the default console. | ||
3129 | * | ||
3130 | * RETURNS: | ||
3131 | * -ENODEV if @csw isn't a registered console driver or can't be unregistered | ||
3132 | * or 0 on success. | ||
3133 | */ | ||
3134 | int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | ||
3135 | { | ||
3136 | int retval; | ||
3137 | |||
3138 | console_lock(); | ||
3139 | retval = do_unbind_con_driver(csw, first, last, deflt); | ||
3140 | console_unlock(); | ||
3141 | return retval; | ||
3142 | } | ||
3143 | EXPORT_SYMBOL(unbind_con_driver); | ||
3144 | |||
3145 | /* unlocked version of unbind_con_driver() */ | 3106 | /* unlocked version of unbind_con_driver() */ |
3146 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | 3107 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) |
3147 | { | 3108 | { |
@@ -3262,8 +3223,11 @@ static int vt_bind(struct con_driver *con) | |||
3262 | if (first == 0 && last == MAX_NR_CONSOLES -1) | 3223 | if (first == 0 && last == MAX_NR_CONSOLES -1) |
3263 | deflt = 1; | 3224 | deflt = 1; |
3264 | 3225 | ||
3265 | if (first != -1) | 3226 | if (first != -1) { |
3266 | bind_con_driver(csw, first, last, deflt); | 3227 | console_lock(); |
3228 | do_bind_con_driver(csw, first, last, deflt); | ||
3229 | console_unlock(); | ||
3230 | } | ||
3267 | 3231 | ||
3268 | first = -1; | 3232 | first = -1; |
3269 | last = -1; | 3233 | last = -1; |
@@ -3301,8 +3265,11 @@ static int vt_unbind(struct con_driver *con) | |||
3301 | if (first == 0 && last == MAX_NR_CONSOLES -1) | 3265 | if (first == 0 && last == MAX_NR_CONSOLES -1) |
3302 | deflt = 1; | 3266 | deflt = 1; |
3303 | 3267 | ||
3304 | if (first != -1) | 3268 | if (first != -1) { |
3305 | unbind_con_driver(csw, first, last, deflt); | 3269 | console_lock(); |
3270 | do_unbind_con_driver(csw, first, last, deflt); | ||
3271 | console_unlock(); | ||
3272 | } | ||
3306 | 3273 | ||
3307 | first = -1; | 3274 | first = -1; |
3308 | last = -1; | 3275 | last = -1; |
@@ -3574,29 +3541,9 @@ err: | |||
3574 | return retval; | 3541 | return retval; |
3575 | } | 3542 | } |
3576 | 3543 | ||
3577 | /** | ||
3578 | * register_con_driver - register console driver to console layer | ||
3579 | * @csw: console driver | ||
3580 | * @first: the first console to take over, minimum value is 0 | ||
3581 | * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 | ||
3582 | * | ||
3583 | * DESCRIPTION: This function registers a console driver which can later | ||
3584 | * bind to a range of consoles specified by @first and @last. It will | ||
3585 | * also initialize the console driver by calling con_startup(). | ||
3586 | */ | ||
3587 | int register_con_driver(const struct consw *csw, int first, int last) | ||
3588 | { | ||
3589 | int retval; | ||
3590 | |||
3591 | console_lock(); | ||
3592 | retval = do_register_con_driver(csw, first, last); | ||
3593 | console_unlock(); | ||
3594 | return retval; | ||
3595 | } | ||
3596 | EXPORT_SYMBOL(register_con_driver); | ||
3597 | 3544 | ||
3598 | /** | 3545 | /** |
3599 | * unregister_con_driver - unregister console driver from console layer | 3546 | * do_unregister_con_driver - unregister console driver from console layer |
3600 | * @csw: console driver | 3547 | * @csw: console driver |
3601 | * | 3548 | * |
3602 | * DESCRIPTION: All drivers that registers to the console layer must | 3549 | * DESCRIPTION: All drivers that registers to the console layer must |
@@ -3606,17 +3553,6 @@ EXPORT_SYMBOL(register_con_driver); | |||
3606 | * | 3553 | * |
3607 | * The driver must unbind first prior to unregistration. | 3554 | * The driver must unbind first prior to unregistration. |
3608 | */ | 3555 | */ |
3609 | int unregister_con_driver(const struct consw *csw) | ||
3610 | { | ||
3611 | int retval; | ||
3612 | |||
3613 | console_lock(); | ||
3614 | retval = do_unregister_con_driver(csw); | ||
3615 | console_unlock(); | ||
3616 | return retval; | ||
3617 | } | ||
3618 | EXPORT_SYMBOL(unregister_con_driver); | ||
3619 | |||
3620 | int do_unregister_con_driver(const struct consw *csw) | 3556 | int do_unregister_con_driver(const struct consw *csw) |
3621 | { | 3557 | { |
3622 | int i, retval = -ENODEV; | 3558 | int i, retval = -ENODEV; |
@@ -3654,7 +3590,7 @@ EXPORT_SYMBOL_GPL(do_unregister_con_driver); | |||
3654 | * when a driver wants to take over some existing consoles | 3590 | * when a driver wants to take over some existing consoles |
3655 | * and become default driver for newly opened ones. | 3591 | * and become default driver for newly opened ones. |
3656 | * | 3592 | * |
3657 | * take_over_console is basically a register followed by unbind | 3593 | * do_take_over_console is basically a register followed by unbind |
3658 | */ | 3594 | */ |
3659 | int do_take_over_console(const struct consw *csw, int first, int last, int deflt) | 3595 | int do_take_over_console(const struct consw *csw, int first, int last, int deflt) |
3660 | { | 3596 | { |
@@ -3675,30 +3611,6 @@ int do_take_over_console(const struct consw *csw, int first, int last, int deflt | |||
3675 | } | 3611 | } |
3676 | EXPORT_SYMBOL_GPL(do_take_over_console); | 3612 | EXPORT_SYMBOL_GPL(do_take_over_console); |
3677 | 3613 | ||
3678 | /* | ||
3679 | * If we support more console drivers, this function is used | ||
3680 | * when a driver wants to take over some existing consoles | ||
3681 | * and become default driver for newly opened ones. | ||
3682 | * | ||
3683 | * take_over_console is basically a register followed by unbind | ||
3684 | */ | ||
3685 | int take_over_console(const struct consw *csw, int first, int last, int deflt) | ||
3686 | { | ||
3687 | int err; | ||
3688 | |||
3689 | err = register_con_driver(csw, first, last); | ||
3690 | /* | ||
3691 | * If we get an busy error we still want to bind the console driver | ||
3692 | * and return success, as we may have unbound the console driver | ||
3693 | * but not unregistered it. | ||
3694 | */ | ||
3695 | if (err == -EBUSY) | ||
3696 | err = 0; | ||
3697 | if (!err) | ||
3698 | bind_con_driver(csw, first, last, deflt); | ||
3699 | |||
3700 | return err; | ||
3701 | } | ||
3702 | 3614 | ||
3703 | /* | 3615 | /* |
3704 | * give_up_console is a wrapper to unregister_con_driver. It will only | 3616 | * give_up_console is a wrapper to unregister_con_driver. It will only |
@@ -3706,7 +3618,9 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt) | |||
3706 | */ | 3618 | */ |
3707 | void give_up_console(const struct consw *csw) | 3619 | void give_up_console(const struct consw *csw) |
3708 | { | 3620 | { |
3709 | unregister_con_driver(csw); | 3621 | console_lock(); |
3622 | do_unregister_con_driver(csw); | ||
3623 | console_unlock(); | ||
3710 | } | 3624 | } |
3711 | 3625 | ||
3712 | static int __init vtconsole_class_init(void) | 3626 | static int __init vtconsole_class_init(void) |
@@ -4262,6 +4176,5 @@ EXPORT_SYMBOL(console_blanked); | |||
4262 | EXPORT_SYMBOL(vc_cons); | 4176 | EXPORT_SYMBOL(vc_cons); |
4263 | EXPORT_SYMBOL(global_cursor_default); | 4177 | EXPORT_SYMBOL(global_cursor_default); |
4264 | #ifndef VT_SINGLE_DRIVER | 4178 | #ifndef VT_SINGLE_DRIVER |
4265 | EXPORT_SYMBOL(take_over_console); | ||
4266 | EXPORT_SYMBOL(give_up_console); | 4179 | EXPORT_SYMBOL(give_up_console); |
4267 | #endif | 4180 | #endif |