aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-02-26 06:01:53 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-26 16:06:13 -0500
commitc728cc88cec52a6bf97679ed4353bc42ff25e6ab (patch)
tree37d77f03a9d6a9046ad8e850d65a26ea8b23a208 /drivers/isdn
parente5b3fa1547283b25d5e68ad2563b7e7dd8cb1209 (diff)
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>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/hisax/elsa.c9
-rw-r--r--drivers/isdn/hisax/elsa_ser.c3
2 files changed, 8 insertions, 4 deletions
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 2be1c8a3bb5f..d8ef64da26f1 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -509,7 +509,8 @@ static void
509set_arcofi(struct IsdnCardState *cs, int bc) { 509set_arcofi(struct IsdnCardState *cs, int bc) {
510 cs->dc.isac.arcofi_bc = bc; 510 cs->dc.isac.arcofi_bc = bc;
511 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5); 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
515static int 516static int
@@ -528,7 +529,8 @@ check_arcofi(struct IsdnCardState *cs)
528 } 529 }
529 cs->dc.isac.arcofi_bc = 0; 530 cs->dc.isac.arcofi_bc = 0;
530 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION); 531 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
531 interruptible_sleep_on(&cs->dc.isac.arcofi_wait); 532 wait_event_interruptible(cs->dc.isac.arcofi_wait,
533 cs->dc.isac.arcofi_state == ARCOFI_NOP);
532 if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) { 534 if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
533 debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp); 535 debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
534 p = cs->dc.isac.mon_rx; 536 p = cs->dc.isac.mon_rx;
@@ -595,7 +597,8 @@ check_arcofi(struct IsdnCardState *cs)
595 Elsa_Types[cs->subtyp], 597 Elsa_Types[cs->subtyp],
596 cs->hw.elsa.base + 8); 598 cs->hw.elsa.base + 8);
597 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0); 599 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
598 interruptible_sleep_on(&cs->dc.isac.arcofi_wait); 600 wait_event_interruptible(cs->dc.isac.arcofi_wait,
601 cs->dc.isac.arcofi_state == ARCOFI_NOP);
599 return (1); 602 return (1);
600 } 603 }
601 return (0); 604 return (0);
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 3f84dd8f1757..a2a358c1dc8e 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -573,7 +573,8 @@ modem_l2l1(struct PStack *st, int pr, void *arg)
573 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); 573 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
574 bcs->cs->dc.isac.arcofi_bc = st->l1.bc; 574 bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
575 arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); 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 bcs->cs->hw.elsa.MFlag = 1; 578 bcs->cs->hw.elsa.MFlag = 1;
578 } else { 579 } else {
579 printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr); 580 printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr);