Skip to contentSkip to conversation

synclink_gt fix missed serial input signal changes

PATCH New Paul Fulghum 1 participant 1 message Jan 28, 2008 Char and misc drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 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.

drivers/char/synclink_gt.c +37 -31
@@ -2040,37 +2040,41 @@ static void bh_transmit(struct slgt_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;
@@ -2091,20 +2095,21 @@ static void cts_change(struct slgt_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)
@@ -2127,20 +2132,21 @@ static void dcd_change(struct slgt_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;
@@ -2191,13 +2197,13 @@ static void isr_serial(struct slgt_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)