diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-02-26 06:01:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-26 16:06:13 -0500 |
commit | c728cc88cec52a6bf97679ed4353bc42ff25e6ab (patch) | |
tree | 37d77f03a9d6a9046ad8e850d65a26ea8b23a208 /drivers/isdn | |
parent | e5b3fa1547283b25d5e68ad2563b7e7dd8cb1209 (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.c | 9 | ||||
-rw-r--r-- | drivers/isdn/hisax/elsa_ser.c | 3 |
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 | |||
509 | set_arcofi(struct IsdnCardState *cs, int bc) { | 509 | set_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 | ||
515 | static int | 516 | static 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); |