aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorPaul Fulghum <paulkf@microgate.com>2008-02-06 04:37:18 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:06 -0500
commited8485fb340056c4d9062e9d2697c8402dd19eb0 (patch)
tree3426e53cf4673da90d8348ae5c45fb1cc8f3ea7f /drivers/char
parent3dd1247f4dee214a92b42e17818703ea71233288 (diff)
synclink_gt fix missed serial input signal changes
Fix missed serial input signal changes caused by rereading the serial status register during interrupt processing. Now processing is performed on original status register value. Signed-off-by: Paul Fulghum <paulkf@microgate.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/synclink_gt.c68
1 files changed, 37 insertions, 31 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 5f6a5da696c7..1f954acf2bac 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -2039,37 +2039,41 @@ static void bh_transmit(struct slgt_info *info)
2039 tty_wakeup(tty); 2039 tty_wakeup(tty);
2040} 2040}
2041 2041
2042static void dsr_change(struct slgt_info *info) 2042static void dsr_change(struct slgt_info *info, unsigned short status)
2043{ 2043{
2044 get_signals(info); 2044 if (status & BIT3) {
2045 info->signals |= SerialSignal_DSR;
2046 info->input_signal_events.dsr_up++;
2047 } else {
2048 info->signals &= ~SerialSignal_DSR;
2049 info->input_signal_events.dsr_down++;
2050 }
2045 DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); 2051 DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
2046 if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { 2052 if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
2047 slgt_irq_off(info, IRQ_DSR); 2053 slgt_irq_off(info, IRQ_DSR);
2048 return; 2054 return;
2049 } 2055 }
2050 info->icount.dsr++; 2056 info->icount.dsr++;
2051 if (info->signals & SerialSignal_DSR)
2052 info->input_signal_events.dsr_up++;
2053 else
2054 info->input_signal_events.dsr_down++;
2055 wake_up_interruptible(&info->status_event_wait_q); 2057 wake_up_interruptible(&info->status_event_wait_q);
2056 wake_up_interruptible(&info->event_wait_q); 2058 wake_up_interruptible(&info->event_wait_q);
2057 info->pending_bh |= BH_STATUS; 2059 info->pending_bh |= BH_STATUS;
2058} 2060}
2059 2061
2060static void cts_change(struct slgt_info *info) 2062static void cts_change(struct slgt_info *info, unsigned short status)
2061{ 2063{
2062 get_signals(info); 2064 if (status & BIT2) {
2065 info->signals |= SerialSignal_CTS;
2066 info->input_signal_events.cts_up++;
2067 } else {
2068 info->signals &= ~SerialSignal_CTS;
2069 info->input_signal_events.cts_down++;
2070 }
2063 DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); 2071 DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
2064 if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { 2072 if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
2065 slgt_irq_off(info, IRQ_CTS); 2073 slgt_irq_off(info, IRQ_CTS);
2066 return; 2074 return;
2067 } 2075 }
2068 info->icount.cts++; 2076 info->icount.cts++;
2069 if (info->signals & SerialSignal_CTS)
2070 info->input_signal_events.cts_up++;
2071 else
2072 info->input_signal_events.cts_down++;
2073 wake_up_interruptible(&info->status_event_wait_q); 2077 wake_up_interruptible(&info->status_event_wait_q);
2074 wake_up_interruptible(&info->event_wait_q); 2078 wake_up_interruptible(&info->event_wait_q);
2075 info->pending_bh |= BH_STATUS; 2079 info->pending_bh |= BH_STATUS;
@@ -2090,20 +2094,21 @@ static void cts_change(struct slgt_info *info)
2090 } 2094 }
2091} 2095}
2092 2096
2093static void dcd_change(struct slgt_info *info) 2097static void dcd_change(struct slgt_info *info, unsigned short status)
2094{ 2098{
2095 get_signals(info); 2099 if (status & BIT1) {
2100 info->signals |= SerialSignal_DCD;
2101 info->input_signal_events.dcd_up++;
2102 } else {
2103 info->signals &= ~SerialSignal_DCD;
2104 info->input_signal_events.dcd_down++;
2105 }
2096 DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); 2106 DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
2097 if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { 2107 if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
2098 slgt_irq_off(info, IRQ_DCD); 2108 slgt_irq_off(info, IRQ_DCD);
2099 return; 2109 return;
2100 } 2110 }
2101 info->icount.dcd++; 2111 info->icount.dcd++;
2102 if (info->signals & SerialSignal_DCD) {
2103 info->input_signal_events.dcd_up++;
2104 } else {
2105 info->input_signal_events.dcd_down++;
2106 }
2107#if SYNCLINK_GENERIC_HDLC 2112#if SYNCLINK_GENERIC_HDLC
2108 if (info->netcount) { 2113 if (info->netcount) {
2109 if (info->signals & SerialSignal_DCD) 2114 if (info->signals & SerialSignal_DCD)
@@ -2126,20 +2131,21 @@ static void dcd_change(struct slgt_info *info)
2126 } 2131 }
2127} 2132}
2128 2133
2129static void ri_change(struct slgt_info *info) 2134static void ri_change(struct slgt_info *info, unsigned short status)
2130{ 2135{
2131 get_signals(info); 2136 if (status & BIT0) {
2137 info->signals |= SerialSignal_RI;
2138 info->input_signal_events.ri_up++;
2139 } else {
2140 info->signals &= ~SerialSignal_RI;
2141 info->input_signal_events.ri_down++;
2142 }
2132 DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); 2143 DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
2133 if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { 2144 if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
2134 slgt_irq_off(info, IRQ_RI); 2145 slgt_irq_off(info, IRQ_RI);
2135 return; 2146 return;
2136 } 2147 }
2137 info->icount.dcd++; 2148 info->icount.rng++;
2138 if (info->signals & SerialSignal_RI) {
2139 info->input_signal_events.ri_up++;
2140 } else {
2141 info->input_signal_events.ri_down++;
2142 }
2143 wake_up_interruptible(&info->status_event_wait_q); 2149 wake_up_interruptible(&info->status_event_wait_q);
2144 wake_up_interruptible(&info->event_wait_q); 2150 wake_up_interruptible(&info->event_wait_q);
2145 info->pending_bh |= BH_STATUS; 2151 info->pending_bh |= BH_STATUS;
@@ -2190,13 +2196,13 @@ static void isr_serial(struct slgt_info *info)
2190 } 2196 }
2191 2197
2192 if (status & IRQ_DSR) 2198 if (status & IRQ_DSR)
2193 dsr_change(info); 2199 dsr_change(info, status);
2194 if (status & IRQ_CTS) 2200 if (status & IRQ_CTS)
2195 cts_change(info); 2201 cts_change(info, status);
2196 if (status & IRQ_DCD) 2202 if (status & IRQ_DCD)
2197 dcd_change(info); 2203 dcd_change(info, status);
2198 if (status & IRQ_RI) 2204 if (status & IRQ_RI)
2199 ri_change(info); 2205 ri_change(info, status);
2200} 2206}
2201 2207
2202static void isr_rdma(struct slgt_info *info) 2208static void isr_rdma(struct slgt_info *info)