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>
This commit is contained in:
parent
3dd1247f4d
commit
ed8485fb34
1 changed files with 37 additions and 31 deletions
|
@ -2039,37 +2039,41 @@ static void bh_transmit(struct slgt_info *info)
|
||||||
tty_wakeup(tty);
|
tty_wakeup(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dsr_change(struct slgt_info *info)
|
static void dsr_change(struct slgt_info *info, unsigned short status)
|
||||||
{
|
{
|
||||||
get_signals(info);
|
if (status & BIT3) {
|
||||||
|
info->signals |= SerialSignal_DSR;
|
||||||
|
info->input_signal_events.dsr_up++;
|
||||||
|
} else {
|
||||||
|
info->signals &= ~SerialSignal_DSR;
|
||||||
|
info->input_signal_events.dsr_down++;
|
||||||
|
}
|
||||||
DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
|
DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
|
||||||
if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
||||||
slgt_irq_off(info, IRQ_DSR);
|
slgt_irq_off(info, IRQ_DSR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info->icount.dsr++;
|
info->icount.dsr++;
|
||||||
if (info->signals & SerialSignal_DSR)
|
|
||||||
info->input_signal_events.dsr_up++;
|
|
||||||
else
|
|
||||||
info->input_signal_events.dsr_down++;
|
|
||||||
wake_up_interruptible(&info->status_event_wait_q);
|
wake_up_interruptible(&info->status_event_wait_q);
|
||||||
wake_up_interruptible(&info->event_wait_q);
|
wake_up_interruptible(&info->event_wait_q);
|
||||||
info->pending_bh |= BH_STATUS;
|
info->pending_bh |= BH_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cts_change(struct slgt_info *info)
|
static void cts_change(struct slgt_info *info, unsigned short status)
|
||||||
{
|
{
|
||||||
get_signals(info);
|
if (status & BIT2) {
|
||||||
|
info->signals |= SerialSignal_CTS;
|
||||||
|
info->input_signal_events.cts_up++;
|
||||||
|
} else {
|
||||||
|
info->signals &= ~SerialSignal_CTS;
|
||||||
|
info->input_signal_events.cts_down++;
|
||||||
|
}
|
||||||
DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
|
DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
|
||||||
if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
||||||
slgt_irq_off(info, IRQ_CTS);
|
slgt_irq_off(info, IRQ_CTS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info->icount.cts++;
|
info->icount.cts++;
|
||||||
if (info->signals & SerialSignal_CTS)
|
|
||||||
info->input_signal_events.cts_up++;
|
|
||||||
else
|
|
||||||
info->input_signal_events.cts_down++;
|
|
||||||
wake_up_interruptible(&info->status_event_wait_q);
|
wake_up_interruptible(&info->status_event_wait_q);
|
||||||
wake_up_interruptible(&info->event_wait_q);
|
wake_up_interruptible(&info->event_wait_q);
|
||||||
info->pending_bh |= BH_STATUS;
|
info->pending_bh |= BH_STATUS;
|
||||||
|
@ -2090,20 +2094,21 @@ static void cts_change(struct slgt_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dcd_change(struct slgt_info *info)
|
static void dcd_change(struct slgt_info *info, unsigned short status)
|
||||||
{
|
{
|
||||||
get_signals(info);
|
if (status & BIT1) {
|
||||||
|
info->signals |= SerialSignal_DCD;
|
||||||
|
info->input_signal_events.dcd_up++;
|
||||||
|
} else {
|
||||||
|
info->signals &= ~SerialSignal_DCD;
|
||||||
|
info->input_signal_events.dcd_down++;
|
||||||
|
}
|
||||||
DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
|
DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
|
||||||
if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
||||||
slgt_irq_off(info, IRQ_DCD);
|
slgt_irq_off(info, IRQ_DCD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info->icount.dcd++;
|
info->icount.dcd++;
|
||||||
if (info->signals & SerialSignal_DCD) {
|
|
||||||
info->input_signal_events.dcd_up++;
|
|
||||||
} else {
|
|
||||||
info->input_signal_events.dcd_down++;
|
|
||||||
}
|
|
||||||
#if SYNCLINK_GENERIC_HDLC
|
#if SYNCLINK_GENERIC_HDLC
|
||||||
if (info->netcount) {
|
if (info->netcount) {
|
||||||
if (info->signals & SerialSignal_DCD)
|
if (info->signals & SerialSignal_DCD)
|
||||||
|
@ -2126,20 +2131,21 @@ static void dcd_change(struct slgt_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ri_change(struct slgt_info *info)
|
static void ri_change(struct slgt_info *info, unsigned short status)
|
||||||
{
|
{
|
||||||
get_signals(info);
|
if (status & BIT0) {
|
||||||
|
info->signals |= SerialSignal_RI;
|
||||||
|
info->input_signal_events.ri_up++;
|
||||||
|
} else {
|
||||||
|
info->signals &= ~SerialSignal_RI;
|
||||||
|
info->input_signal_events.ri_down++;
|
||||||
|
}
|
||||||
DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
|
DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
|
||||||
if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
|
||||||
slgt_irq_off(info, IRQ_RI);
|
slgt_irq_off(info, IRQ_RI);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info->icount.dcd++;
|
info->icount.rng++;
|
||||||
if (info->signals & SerialSignal_RI) {
|
|
||||||
info->input_signal_events.ri_up++;
|
|
||||||
} else {
|
|
||||||
info->input_signal_events.ri_down++;
|
|
||||||
}
|
|
||||||
wake_up_interruptible(&info->status_event_wait_q);
|
wake_up_interruptible(&info->status_event_wait_q);
|
||||||
wake_up_interruptible(&info->event_wait_q);
|
wake_up_interruptible(&info->event_wait_q);
|
||||||
info->pending_bh |= BH_STATUS;
|
info->pending_bh |= BH_STATUS;
|
||||||
|
@ -2190,13 +2196,13 @@ static void isr_serial(struct slgt_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & IRQ_DSR)
|
if (status & IRQ_DSR)
|
||||||
dsr_change(info);
|
dsr_change(info, status);
|
||||||
if (status & IRQ_CTS)
|
if (status & IRQ_CTS)
|
||||||
cts_change(info);
|
cts_change(info, status);
|
||||||
if (status & IRQ_DCD)
|
if (status & IRQ_DCD)
|
||||||
dcd_change(info);
|
dcd_change(info, status);
|
||||||
if (status & IRQ_RI)
|
if (status & IRQ_RI)
|
||||||
ri_change(info);
|
ri_change(info, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void isr_rdma(struct slgt_info *info)
|
static void isr_rdma(struct slgt_info *info)
|
||||||
|
|
Reference in a new issue