Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c728cc88 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by David S. Miller
Browse files

isdn: hisax/elsa: fix sleep_on race in elsa FSM



The state machine code in the elsa driver uses interruptible_sleep_on
to wait for state changes, which is racy. A closer look at the possible
states reveals that it is always used to wait for getting back into
ARCOFI_NOP, so we can use wait_event_interruptible instead.

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Cc: Karsten Keil <isdn@linux-pingi.de>
Cc: netdev@vger.kernel.org
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e5b3fa15
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -509,7 +509,8 @@ static void
set_arcofi(struct IsdnCardState *cs, int bc) {
	cs->dc.isac.arcofi_bc = bc;
	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);
	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
	wait_event_interruptible(cs->dc.isac.arcofi_wait,
				 cs->dc.isac.arcofi_state == ARCOFI_NOP);
}

static int
@@ -528,7 +529,8 @@ check_arcofi(struct IsdnCardState *cs)
		}
	cs->dc.isac.arcofi_bc = 0;
	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
	wait_event_interruptible(cs->dc.isac.arcofi_wait,
				 cs->dc.isac.arcofi_state == ARCOFI_NOP);
	if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
		debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
		p = cs->dc.isac.mon_rx;
@@ -595,7 +597,8 @@ check_arcofi(struct IsdnCardState *cs)
			       Elsa_Types[cs->subtyp],
			       cs->hw.elsa.base + 8);
		arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
		interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
		wait_event_interruptible(cs->dc.isac.arcofi_wait,
				 cs->dc.isac.arcofi_state == ARCOFI_NOP);
		return (1);
	}
	return (0);
+2 −1
Original line number Diff line number Diff line
@@ -573,7 +573,8 @@ modem_l2l1(struct PStack *st, int pr, void *arg)
		test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
		bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
		arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
		interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait);
		wait_event_interruptible(bcs->cs->dc.isac.arcofi_wait,
				 bcs->cs->dc.isac.arcofi_state == ARCOFI_NOP);
		bcs->cs->hw.elsa.MFlag = 1;
	} else {
		printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr);