[PATCH] drivers/isdn/hysdn/hysdn_sched.c: sleep after taking spinlock fix
spin_lock_irq{save,restore} is incorrectly called here (the function can sleep after acquring the lock). done the necessary corrections and removed unwanted cli/sti. Signed-off-by: Amol Lad <amol@verismonetworks.com> Signed-off-by: Karsten Keil <kkeil@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
@@ -155,21 +155,17 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan)
|
|||||||
if (card->debug_flags & LOG_SCHED_ASYN)
|
if (card->debug_flags & LOG_SCHED_ASYN)
|
||||||
hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
|
hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
|
||||||
|
|
||||||
spin_lock_irqsave(&card->hysdn_lock, flags);
|
|
||||||
while (card->async_busy) {
|
while (card->async_busy) {
|
||||||
sti();
|
|
||||||
|
|
||||||
if (card->debug_flags & LOG_SCHED_ASYN)
|
if (card->debug_flags & LOG_SCHED_ASYN)
|
||||||
hysdn_addlog(card, "async tx-cfg delayed");
|
hysdn_addlog(card, "async tx-cfg delayed");
|
||||||
|
|
||||||
msleep_interruptible(20); /* Timeout 20ms */
|
msleep_interruptible(20); /* Timeout 20ms */
|
||||||
if (!--cnt) {
|
if (!--cnt)
|
||||||
spin_unlock_irqrestore(&card->hysdn_lock, flags);
|
|
||||||
return (-ERR_ASYNC_TIME); /* timed out */
|
return (-ERR_ASYNC_TIME); /* timed out */
|
||||||
}
|
|
||||||
cli();
|
|
||||||
} /* wait for buffer to become free */
|
} /* wait for buffer to become free */
|
||||||
|
|
||||||
|
spin_lock_irqsave(&card->hysdn_lock, flags);
|
||||||
strcpy(card->async_data, line);
|
strcpy(card->async_data, line);
|
||||||
card->async_len = strlen(line) + 1;
|
card->async_len = strlen(line) + 1;
|
||||||
card->async_channel = chan;
|
card->async_channel = chan;
|
||||||
@@ -177,30 +173,23 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan)
|
|||||||
|
|
||||||
/* now queue the task */
|
/* now queue the task */
|
||||||
schedule_work(&card->irq_queue);
|
schedule_work(&card->irq_queue);
|
||||||
sti();
|
spin_unlock_irqrestore(&card->hysdn_lock, flags);
|
||||||
|
|
||||||
if (card->debug_flags & LOG_SCHED_ASYN)
|
if (card->debug_flags & LOG_SCHED_ASYN)
|
||||||
hysdn_addlog(card, "async tx-cfg data queued");
|
hysdn_addlog(card, "async tx-cfg data queued");
|
||||||
|
|
||||||
cnt++; /* short delay */
|
cnt++; /* short delay */
|
||||||
cli();
|
|
||||||
|
|
||||||
while (card->async_busy) {
|
while (card->async_busy) {
|
||||||
sti();
|
|
||||||
|
|
||||||
if (card->debug_flags & LOG_SCHED_ASYN)
|
if (card->debug_flags & LOG_SCHED_ASYN)
|
||||||
hysdn_addlog(card, "async tx-cfg waiting for tx-ready");
|
hysdn_addlog(card, "async tx-cfg waiting for tx-ready");
|
||||||
|
|
||||||
msleep_interruptible(20); /* Timeout 20ms */
|
msleep_interruptible(20); /* Timeout 20ms */
|
||||||
if (!--cnt) {
|
if (!--cnt)
|
||||||
spin_unlock_irqrestore(&card->hysdn_lock, flags);
|
|
||||||
return (-ERR_ASYNC_TIME); /* timed out */
|
return (-ERR_ASYNC_TIME); /* timed out */
|
||||||
}
|
|
||||||
cli();
|
|
||||||
} /* wait for buffer to become free again */
|
} /* wait for buffer to become free again */
|
||||||
|
|
||||||
spin_unlock_irqrestore(&card->hysdn_lock, flags);
|
|
||||||
|
|
||||||
if (card->debug_flags & LOG_SCHED_ASYN)
|
if (card->debug_flags & LOG_SCHED_ASYN)
|
||||||
hysdn_addlog(card, "async tx-cfg data send");
|
hysdn_addlog(card, "async tx-cfg data send");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user