Skip to content

Commit

Permalink
synclink_gt fix missed serial input signal changes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Fulghum authored and Linus Torvalds committed Feb 6, 2008
1 parent 3dd1247 commit ed8485f
Showing 1 changed file with 37 additions and 31 deletions.
68 changes: 37 additions & 31 deletions drivers/char/synclink_gt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,37 +2039,41 @@ static void bh_transmit(struct slgt_info *info)
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));
if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_DSR);
return;
}
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->event_wait_q);
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));
if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_CTS);
return;
}
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->event_wait_q);
info->pending_bh |= BH_STATUS;
Expand All @@ -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));
if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_DCD);
return;
}
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 (info->netcount) {
if (info->signals & SerialSignal_DCD)
Expand All @@ -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));
if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_RI);
return;
}
info->icount.dcd++;
if (info->signals & SerialSignal_RI) {
info->input_signal_events.ri_up++;
} else {
info->input_signal_events.ri_down++;
}
info->icount.rng++;
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
info->pending_bh |= BH_STATUS;
Expand Down Expand Up @@ -2190,13 +2196,13 @@ static void isr_serial(struct slgt_info *info)
}

if (status & IRQ_DSR)
dsr_change(info);
dsr_change(info, status);
if (status & IRQ_CTS)
cts_change(info);
cts_change(info, status);
if (status & IRQ_DCD)
dcd_change(info);
dcd_change(info, status);
if (status & IRQ_RI)
ri_change(info);
ri_change(info, status);
}

static void isr_rdma(struct slgt_info *info)
Expand Down

0 comments on commit ed8485f

Please sign in to comment.