Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Arnd Bergmann <arnd@arndb.de>
Cc: Karsten Keil <isdn@linux-pingi.de>
Cc: netdev@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arnd Bergmann and committed by
David S. Miller
c728cc88 e5b3fa15

+8 -4
+6 -3
drivers/isdn/hisax/elsa.c
··· 509 509 set_arcofi(struct IsdnCardState *cs, int bc) { 510 510 cs->dc.isac.arcofi_bc = bc; 511 511 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5); 512 - interruptible_sleep_on(&cs->dc.isac.arcofi_wait); 512 + wait_event_interruptible(cs->dc.isac.arcofi_wait, 513 + cs->dc.isac.arcofi_state == ARCOFI_NOP); 513 514 } 514 515 515 516 static int ··· 529 528 } 530 529 cs->dc.isac.arcofi_bc = 0; 531 530 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION); 532 - interruptible_sleep_on(&cs->dc.isac.arcofi_wait); 531 + wait_event_interruptible(cs->dc.isac.arcofi_wait, 532 + cs->dc.isac.arcofi_state == ARCOFI_NOP); 533 533 if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) { 534 534 debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp); 535 535 p = cs->dc.isac.mon_rx; ··· 597 595 Elsa_Types[cs->subtyp], 598 596 cs->hw.elsa.base + 8); 599 597 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0); 600 - interruptible_sleep_on(&cs->dc.isac.arcofi_wait); 598 + wait_event_interruptible(cs->dc.isac.arcofi_wait, 599 + cs->dc.isac.arcofi_state == ARCOFI_NOP); 601 600 return (1); 602 601 } 603 602 return (0);
+2 -1
drivers/isdn/hisax/elsa_ser.c
··· 573 573 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); 574 574 bcs->cs->dc.isac.arcofi_bc = st->l1.bc; 575 575 arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); 576 - interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait); 576 + wait_event_interruptible(bcs->cs->dc.isac.arcofi_wait, 577 + bcs->cs->dc.isac.arcofi_state == ARCOFI_NOP); 577 578 bcs->cs->hw.elsa.MFlag = 1; 578 579 } else { 579 580 printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr);