From: Arnd Bergmann Date: Wed, 26 Feb 2014 11:01:52 +0000 (+0100) Subject: isdn: pcbit: fix interruptible_sleep_on race X-Git-Tag: firefly_0821_release~176^2~4167^2~253 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e5b3fa1547283b25d5e68ad2563b7e7dd8cb1209;p=firefly-linux-kernel-4.4.55.git isdn: pcbit: fix interruptible_sleep_on race interruptible_sleep_on is racy and going away. In case of pcbit, the driver would run into a timeout if the card is initialized before we start waiting for it. This uses wait_event to fix the race. In order to do this, the state machine handling for the timeout case has to get trivially reorganized so we actually know whether the timeout has occorred or not. Signed-off-by: Arnd Bergmann Cc: Karsten Keil Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 1eaf62273903..f02cc506fbfa 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -796,6 +796,7 @@ static void set_running_timeout(unsigned long ptr) #endif dev = (struct pcbit_dev *) ptr; + dev->l2_state = L2_DOWN; wake_up_interruptible(&dev->set_running_wq); } @@ -818,7 +819,8 @@ static int set_protocol_running(struct pcbit_dev *dev) add_timer(&dev->set_running_timer); - interruptible_sleep_on(&dev->set_running_wq); + wait_event(dev->set_running_wq, dev->l2_state == L2_RUNNING || + dev->l2_state == L2_DOWN); del_timer(&dev->set_running_timer); @@ -842,8 +844,6 @@ static int set_protocol_running(struct pcbit_dev *dev) printk(KERN_DEBUG "pcbit: initialization failed\n"); printk(KERN_DEBUG "pcbit: firmware not loaded\n"); - dev->l2_state = L2_DOWN; - #ifdef DEBUG printk(KERN_DEBUG "Bank3 = %02x\n", readb(dev->sh_mem + BANK3));