diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-23 14:59:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-23 14:59:37 -0400 |
commit | 0f6e38a6381446eff5175b77d1094834a633a90f (patch) | |
tree | e5295c372b6a73fa84b4d14b86ea9fa626d3f030 /drivers | |
parent | e669e8179d364bb11ed51504e1a1c60830bff4c5 (diff) | |
parent | 3b216c9ed347924efb5e7a66b3257c40a5596d30 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb:
kgdb: kgdboc console poll hooks for mpsc uart
kgdb: kgdboc console poll hooks for cpm uart
kgdb, powerpc: arch specific powerpc kgdb support
kgdb: support for ARCH=arm
kgdb: remove unused HAVE_ARCH_KGDB_SHADOW_INFO config variable
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 95 | ||||
-rw-r--r-- | drivers/serial/mpsc.c | 148 |
2 files changed, 241 insertions, 2 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 93e407ee08b9..1ff80de177db 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -201,6 +201,10 @@ static void cpm_uart_int_tx(struct uart_port *port) | |||
201 | cpm_uart_tx_pump(port); | 201 | cpm_uart_tx_pump(port); |
202 | } | 202 | } |
203 | 203 | ||
204 | #ifdef CONFIG_CONSOLE_POLL | ||
205 | static int serial_polled; | ||
206 | #endif | ||
207 | |||
204 | /* | 208 | /* |
205 | * Receive characters | 209 | * Receive characters |
206 | */ | 210 | */ |
@@ -222,6 +226,12 @@ static void cpm_uart_int_rx(struct uart_port *port) | |||
222 | */ | 226 | */ |
223 | bdp = pinfo->rx_cur; | 227 | bdp = pinfo->rx_cur; |
224 | for (;;) { | 228 | for (;;) { |
229 | #ifdef CONFIG_CONSOLE_POLL | ||
230 | if (unlikely(serial_polled)) { | ||
231 | serial_polled = 0; | ||
232 | return; | ||
233 | } | ||
234 | #endif | ||
225 | /* get status */ | 235 | /* get status */ |
226 | status = in_be16(&bdp->cbd_sc); | 236 | status = in_be16(&bdp->cbd_sc); |
227 | /* If this one is empty, return happy */ | 237 | /* If this one is empty, return happy */ |
@@ -253,7 +263,12 @@ static void cpm_uart_int_rx(struct uart_port *port) | |||
253 | goto handle_error; | 263 | goto handle_error; |
254 | if (uart_handle_sysrq_char(port, ch)) | 264 | if (uart_handle_sysrq_char(port, ch)) |
255 | continue; | 265 | continue; |
256 | 266 | #ifdef CONFIG_CONSOLE_POLL | |
267 | if (unlikely(serial_polled)) { | ||
268 | serial_polled = 0; | ||
269 | return; | ||
270 | } | ||
271 | #endif | ||
257 | error_return: | 272 | error_return: |
258 | tty_insert_flip_char(tty, ch, flg); | 273 | tty_insert_flip_char(tty, ch, flg); |
259 | 274 | ||
@@ -865,6 +880,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags) | |||
865 | cpm_uart_request_port(port); | 880 | cpm_uart_request_port(port); |
866 | } | 881 | } |
867 | } | 882 | } |
883 | |||
884 | #ifdef CONFIG_CONSOLE_POLL | ||
885 | /* Serial polling routines for writing and reading from the uart while | ||
886 | * in an interrupt or debug context. | ||
887 | */ | ||
888 | |||
889 | #define GDB_BUF_SIZE 512 /* power of 2, please */ | ||
890 | |||
891 | static char poll_buf[GDB_BUF_SIZE]; | ||
892 | static char *pollp; | ||
893 | static int poll_chars; | ||
894 | |||
895 | static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo) | ||
896 | { | ||
897 | u_char c, *cp; | ||
898 | volatile cbd_t *bdp; | ||
899 | int i; | ||
900 | |||
901 | /* Get the address of the host memory buffer. | ||
902 | */ | ||
903 | bdp = pinfo->rx_cur; | ||
904 | while (bdp->cbd_sc & BD_SC_EMPTY) | ||
905 | ; | ||
906 | |||
907 | /* If the buffer address is in the CPM DPRAM, don't | ||
908 | * convert it. | ||
909 | */ | ||
910 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); | ||
911 | |||
912 | if (obuf) { | ||
913 | i = c = bdp->cbd_datlen; | ||
914 | while (i-- > 0) | ||
915 | *obuf++ = *cp++; | ||
916 | } else | ||
917 | c = *cp; | ||
918 | bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); | ||
919 | bdp->cbd_sc |= BD_SC_EMPTY; | ||
920 | |||
921 | if (bdp->cbd_sc & BD_SC_WRAP) | ||
922 | bdp = pinfo->rx_bd_base; | ||
923 | else | ||
924 | bdp++; | ||
925 | pinfo->rx_cur = (cbd_t *)bdp; | ||
926 | |||
927 | return (int)c; | ||
928 | } | ||
929 | |||
930 | static int cpm_get_poll_char(struct uart_port *port) | ||
931 | { | ||
932 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | ||
933 | |||
934 | if (!serial_polled) { | ||
935 | serial_polled = 1; | ||
936 | poll_chars = 0; | ||
937 | } | ||
938 | if (poll_chars <= 0) { | ||
939 | poll_chars = poll_wait_key(poll_buf, pinfo); | ||
940 | pollp = poll_buf; | ||
941 | } | ||
942 | poll_chars--; | ||
943 | return *pollp++; | ||
944 | } | ||
945 | |||
946 | static void cpm_put_poll_char(struct uart_port *port, | ||
947 | unsigned char c) | ||
948 | { | ||
949 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | ||
950 | static char ch[2]; | ||
951 | |||
952 | ch[0] = (char)c; | ||
953 | cpm_uart_early_write(pinfo->port.line, ch, 1); | ||
954 | } | ||
955 | #endif /* CONFIG_CONSOLE_POLL */ | ||
956 | |||
868 | static struct uart_ops cpm_uart_pops = { | 957 | static struct uart_ops cpm_uart_pops = { |
869 | .tx_empty = cpm_uart_tx_empty, | 958 | .tx_empty = cpm_uart_tx_empty, |
870 | .set_mctrl = cpm_uart_set_mctrl, | 959 | .set_mctrl = cpm_uart_set_mctrl, |
@@ -882,6 +971,10 @@ static struct uart_ops cpm_uart_pops = { | |||
882 | .request_port = cpm_uart_request_port, | 971 | .request_port = cpm_uart_request_port, |
883 | .config_port = cpm_uart_config_port, | 972 | .config_port = cpm_uart_config_port, |
884 | .verify_port = cpm_uart_verify_port, | 973 | .verify_port = cpm_uart_verify_port, |
974 | #ifdef CONFIG_CONSOLE_POLL | ||
975 | .poll_get_char = cpm_get_poll_char, | ||
976 | .poll_put_char = cpm_put_poll_char, | ||
977 | #endif | ||
885 | }; | 978 | }; |
886 | 979 | ||
887 | struct uart_cpm_port cpm_uart_ports[UART_NR]; | 980 | struct uart_cpm_port cpm_uart_ports[UART_NR]; |
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index c9f53e71f252..61d3ade5286c 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c | |||
@@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi) | |||
921 | return 0; | 921 | return 0; |
922 | } | 922 | } |
923 | 923 | ||
924 | #ifdef CONFIG_CONSOLE_POLL | ||
925 | static int serial_polled; | ||
926 | #endif | ||
927 | |||
924 | /* | 928 | /* |
925 | ****************************************************************************** | 929 | ****************************************************************************** |
926 | * | 930 | * |
@@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi) | |||
956 | while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) | 960 | while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) |
957 | & SDMA_DESC_CMDSTAT_O)) { | 961 | & SDMA_DESC_CMDSTAT_O)) { |
958 | bytes_in = be16_to_cpu(rxre->bytecnt); | 962 | bytes_in = be16_to_cpu(rxre->bytecnt); |
959 | 963 | #ifdef CONFIG_CONSOLE_POLL | |
964 | if (unlikely(serial_polled)) { | ||
965 | serial_polled = 0; | ||
966 | return 0; | ||
967 | } | ||
968 | #endif | ||
960 | /* Following use of tty struct directly is deprecated */ | 969 | /* Following use of tty struct directly is deprecated */ |
961 | if (unlikely(tty_buffer_request_room(tty, bytes_in) | 970 | if (unlikely(tty_buffer_request_room(tty, bytes_in) |
962 | < bytes_in)) { | 971 | < bytes_in)) { |
@@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi) | |||
1017 | if (uart_handle_sysrq_char(&pi->port, *bp)) { | 1026 | if (uart_handle_sysrq_char(&pi->port, *bp)) { |
1018 | bp++; | 1027 | bp++; |
1019 | bytes_in--; | 1028 | bytes_in--; |
1029 | #ifdef CONFIG_CONSOLE_POLL | ||
1030 | if (unlikely(serial_polled)) { | ||
1031 | serial_polled = 0; | ||
1032 | return 0; | ||
1033 | } | ||
1034 | #endif | ||
1020 | goto next_frame; | 1035 | goto next_frame; |
1021 | } | 1036 | } |
1022 | 1037 | ||
@@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
1519 | 1534 | ||
1520 | return rc; | 1535 | return rc; |
1521 | } | 1536 | } |
1537 | #ifdef CONFIG_CONSOLE_POLL | ||
1538 | /* Serial polling routines for writing and reading from the uart while | ||
1539 | * in an interrupt or debug context. | ||
1540 | */ | ||
1541 | |||
1542 | static char poll_buf[2048]; | ||
1543 | static int poll_ptr; | ||
1544 | static int poll_cnt; | ||
1545 | static void mpsc_put_poll_char(struct uart_port *port, | ||
1546 | unsigned char c); | ||
1547 | |||
1548 | static int mpsc_get_poll_char(struct uart_port *port) | ||
1549 | { | ||
1550 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | ||
1551 | struct mpsc_rx_desc *rxre; | ||
1552 | u32 cmdstat, bytes_in, i; | ||
1553 | u8 *bp; | ||
1554 | |||
1555 | if (!serial_polled) | ||
1556 | serial_polled = 1; | ||
1557 | |||
1558 | pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line); | ||
1559 | |||
1560 | if (poll_cnt) { | ||
1561 | poll_cnt--; | ||
1562 | return poll_buf[poll_ptr++]; | ||
1563 | } | ||
1564 | poll_ptr = 0; | ||
1565 | poll_cnt = 0; | ||
1566 | |||
1567 | while (poll_cnt == 0) { | ||
1568 | rxre = (struct mpsc_rx_desc *)(pi->rxr + | ||
1569 | (pi->rxr_posn*MPSC_RXRE_SIZE)); | ||
1570 | dma_cache_sync(pi->port.dev, (void *)rxre, | ||
1571 | MPSC_RXRE_SIZE, DMA_FROM_DEVICE); | ||
1572 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
1573 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
1574 | invalidate_dcache_range((ulong)rxre, | ||
1575 | (ulong)rxre + MPSC_RXRE_SIZE); | ||
1576 | #endif | ||
1577 | /* | ||
1578 | * Loop through Rx descriptors handling ones that have | ||
1579 | * been completed. | ||
1580 | */ | ||
1581 | while (poll_cnt == 0 && | ||
1582 | !((cmdstat = be32_to_cpu(rxre->cmdstat)) & | ||
1583 | SDMA_DESC_CMDSTAT_O)){ | ||
1584 | bytes_in = be16_to_cpu(rxre->bytecnt); | ||
1585 | bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); | ||
1586 | dma_cache_sync(pi->port.dev, (void *) bp, | ||
1587 | MPSC_RXBE_SIZE, DMA_FROM_DEVICE); | ||
1588 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
1589 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
1590 | invalidate_dcache_range((ulong)bp, | ||
1591 | (ulong)bp + MPSC_RXBE_SIZE); | ||
1592 | #endif | ||
1593 | if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR | | ||
1594 | SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) && | ||
1595 | !(cmdstat & pi->port.ignore_status_mask)) { | ||
1596 | poll_buf[poll_cnt] = *bp; | ||
1597 | poll_cnt++; | ||
1598 | } else { | ||
1599 | for (i = 0; i < bytes_in; i++) { | ||
1600 | poll_buf[poll_cnt] = *bp++; | ||
1601 | poll_cnt++; | ||
1602 | } | ||
1603 | pi->port.icount.rx += bytes_in; | ||
1604 | } | ||
1605 | rxre->bytecnt = cpu_to_be16(0); | ||
1606 | wmb(); | ||
1607 | rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | | ||
1608 | SDMA_DESC_CMDSTAT_EI | | ||
1609 | SDMA_DESC_CMDSTAT_F | | ||
1610 | SDMA_DESC_CMDSTAT_L); | ||
1611 | wmb(); | ||
1612 | dma_cache_sync(pi->port.dev, (void *)rxre, | ||
1613 | MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); | ||
1614 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
1615 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
1616 | flush_dcache_range((ulong)rxre, | ||
1617 | (ulong)rxre + MPSC_RXRE_SIZE); | ||
1618 | #endif | ||
1619 | |||
1620 | /* Advance to next descriptor */ | ||
1621 | pi->rxr_posn = (pi->rxr_posn + 1) & | ||
1622 | (MPSC_RXR_ENTRIES - 1); | ||
1623 | rxre = (struct mpsc_rx_desc *)(pi->rxr + | ||
1624 | (pi->rxr_posn * MPSC_RXRE_SIZE)); | ||
1625 | dma_cache_sync(pi->port.dev, (void *)rxre, | ||
1626 | MPSC_RXRE_SIZE, DMA_FROM_DEVICE); | ||
1627 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
1628 | if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ | ||
1629 | invalidate_dcache_range((ulong)rxre, | ||
1630 | (ulong)rxre + MPSC_RXRE_SIZE); | ||
1631 | #endif | ||
1632 | } | ||
1633 | |||
1634 | /* Restart rx engine, if its stopped */ | ||
1635 | if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0) | ||
1636 | mpsc_start_rx(pi); | ||
1637 | } | ||
1638 | if (poll_cnt) { | ||
1639 | poll_cnt--; | ||
1640 | return poll_buf[poll_ptr++]; | ||
1641 | } | ||
1642 | |||
1643 | return 0; | ||
1644 | } | ||
1645 | |||
1646 | |||
1647 | static void mpsc_put_poll_char(struct uart_port *port, | ||
1648 | unsigned char c) | ||
1649 | { | ||
1650 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | ||
1651 | u32 data; | ||
1652 | |||
1653 | data = readl(pi->mpsc_base + MPSC_MPCR); | ||
1654 | writeb(c, pi->mpsc_base + MPSC_CHR_1); | ||
1655 | mb(); | ||
1656 | data = readl(pi->mpsc_base + MPSC_CHR_2); | ||
1657 | data |= MPSC_CHR_2_TTCS; | ||
1658 | writel(data, pi->mpsc_base + MPSC_CHR_2); | ||
1659 | mb(); | ||
1660 | |||
1661 | while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS); | ||
1662 | } | ||
1663 | #endif | ||
1522 | 1664 | ||
1523 | static struct uart_ops mpsc_pops = { | 1665 | static struct uart_ops mpsc_pops = { |
1524 | .tx_empty = mpsc_tx_empty, | 1666 | .tx_empty = mpsc_tx_empty, |
@@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = { | |||
1537 | .request_port = mpsc_request_port, | 1679 | .request_port = mpsc_request_port, |
1538 | .config_port = mpsc_config_port, | 1680 | .config_port = mpsc_config_port, |
1539 | .verify_port = mpsc_verify_port, | 1681 | .verify_port = mpsc_verify_port, |
1682 | #ifdef CONFIG_CONSOLE_POLL | ||
1683 | .poll_get_char = mpsc_get_poll_char, | ||
1684 | .poll_put_char = mpsc_put_poll_char, | ||
1685 | #endif | ||
1540 | }; | 1686 | }; |
1541 | 1687 | ||
1542 | /* | 1688 | /* |