Changed IRQ-handling to use spinlocks instead of cli/sti
This commit is contained in:
parent
276d17903c
commit
89a11781cb
|
@ -59,11 +59,10 @@ ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs)
|
||||||
if (!card->irq_enabled)
|
if (!card->irq_enabled)
|
||||||
return; /* other device interrupting or irq switched off */
|
return; /* other device interrupting or irq switched off */
|
||||||
|
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli(); /* no further irqs allowed */
|
|
||||||
|
|
||||||
if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {
|
if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {
|
||||||
restore_flags(flags); /* restore old state */
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
return; /* no interrupt requested by E1 */
|
return; /* no interrupt requested by E1 */
|
||||||
}
|
}
|
||||||
/* clear any pending ints on the board */
|
/* clear any pending ints on the board */
|
||||||
|
@ -77,7 +76,7 @@ ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs)
|
||||||
queue_task(&card->irq_queue, &tq_immediate);
|
queue_task(&card->irq_queue, &tq_immediate);
|
||||||
mark_bh(IMMEDIATE_BH);
|
mark_bh(IMMEDIATE_BH);
|
||||||
}
|
}
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
} /* ergo_interrupt */
|
} /* ergo_interrupt */
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -97,17 +96,15 @@ ergo_irq_bh(hysdn_card * card)
|
||||||
return; /* invalid call */
|
return; /* invalid call */
|
||||||
|
|
||||||
dpr = card->dpram; /* point to DPRAM */
|
dpr = card->dpram; /* point to DPRAM */
|
||||||
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
|
|
||||||
save_flags(flags);
|
|
||||||
cli();
|
|
||||||
if (card->hw_lock) {
|
if (card->hw_lock) {
|
||||||
restore_flags(flags); /* hardware currently unavailable */
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
card->hw_lock = 1; /* we now lock the hardware */
|
card->hw_lock = 1; /* we now lock the hardware */
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sti(); /* reenable other ints */
|
|
||||||
again = 0; /* assume loop not to be repeated */
|
again = 0; /* assume loop not to be repeated */
|
||||||
|
|
||||||
if (!dpr->ToHyFlag) {
|
if (!dpr->ToHyFlag) {
|
||||||
|
@ -127,15 +124,13 @@ ergo_irq_bh(hysdn_card * card)
|
||||||
again = 1; /* restart loop */
|
again = 1; /* restart loop */
|
||||||
}
|
}
|
||||||
} /* a message has arrived for us */
|
} /* a message has arrived for us */
|
||||||
cli(); /* no further ints */
|
|
||||||
if (again) {
|
if (again) {
|
||||||
dpr->ToHyInt = 1;
|
dpr->ToHyInt = 1;
|
||||||
dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
|
dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
|
||||||
} else
|
} else
|
||||||
card->hw_lock = 0; /* free hardware again */
|
card->hw_lock = 0; /* free hardware again */
|
||||||
} while (again); /* until nothing more to do */
|
} while (again); /* until nothing more to do */
|
||||||
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
restore_flags(flags);
|
|
||||||
} /* ergo_irq_bh */
|
} /* ergo_irq_bh */
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,8 +147,7 @@ ergo_stopcard(hysdn_card * card)
|
||||||
#ifdef CONFIG_HYSDN_CAPI
|
#ifdef CONFIG_HYSDN_CAPI
|
||||||
hycapi_capi_stop(card);
|
hycapi_capi_stop(card);
|
||||||
#endif /* CONFIG_HYSDN_CAPI */
|
#endif /* CONFIG_HYSDN_CAPI */
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli();
|
|
||||||
val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */
|
val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */
|
||||||
val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */
|
val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */
|
||||||
byteout(card->iobase + PCI9050_INTR_REG, val);
|
byteout(card->iobase + PCI9050_INTR_REG, val);
|
||||||
|
@ -161,8 +155,7 @@ ergo_stopcard(hysdn_card * card)
|
||||||
byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */
|
byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */
|
||||||
card->state = CARD_STATE_UNUSED;
|
card->state = CARD_STATE_UNUSED;
|
||||||
card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */
|
card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */
|
||||||
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
restore_flags(flags);
|
|
||||||
} /* ergo_stopcard */
|
} /* ergo_stopcard */
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
@ -177,20 +170,17 @@ ergo_set_errlog_state(hysdn_card * card, int on)
|
||||||
card->err_log_state = ERRLOG_STATE_OFF; /* must be off */
|
card->err_log_state = ERRLOG_STATE_OFF; /* must be off */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli();
|
|
||||||
|
|
||||||
if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||
|
if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||
|
||||||
((card->err_log_state == ERRLOG_STATE_ON) && on)) {
|
((card->err_log_state == ERRLOG_STATE_ON) && on)) {
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
}
|
}
|
||||||
if (on)
|
if (on)
|
||||||
card->err_log_state = ERRLOG_STATE_START; /* request start */
|
card->err_log_state = ERRLOG_STATE_START; /* request start */
|
||||||
else
|
else
|
||||||
card->err_log_state = ERRLOG_STATE_STOP; /* request stop */
|
card->err_log_state = ERRLOG_STATE_STOP; /* request stop */
|
||||||
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
restore_flags(flags);
|
|
||||||
queue_task(&card->irq_queue, &tq_immediate);
|
queue_task(&card->irq_queue, &tq_immediate);
|
||||||
mark_bh(IMMEDIATE_BH);
|
mark_bh(IMMEDIATE_BH);
|
||||||
} /* ergo_set_errlog_state */
|
} /* ergo_set_errlog_state */
|
||||||
|
@ -259,9 +249,6 @@ ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs)
|
||||||
while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */
|
while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */
|
||||||
|
|
||||||
byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */
|
byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */
|
||||||
/* the interrupts are still masked */
|
|
||||||
|
|
||||||
sti();
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
|
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
|
||||||
|
|
||||||
|
@ -296,7 +283,6 @@ ergo_writebootseq(struct HYSDN_CARD *card, uchar * buf, int len)
|
||||||
dst = sp->Data; /* point to data in spool structure */
|
dst = sp->Data; /* point to data in spool structure */
|
||||||
buflen = sp->Len; /* maximum len of spooled data */
|
buflen = sp->Len; /* maximum len of spooled data */
|
||||||
wr_mirror = sp->WrPtr; /* only once read */
|
wr_mirror = sp->WrPtr; /* only once read */
|
||||||
sti();
|
|
||||||
|
|
||||||
/* try until all bytes written or error */
|
/* try until all bytes written or error */
|
||||||
i = 0x1000; /* timeout value */
|
i = 0x1000; /* timeout value */
|
||||||
|
@ -372,9 +358,7 @@ ergo_waitpofready(struct HYSDN_CARD *card)
|
||||||
|
|
||||||
if (card->debug_flags & LOG_POF_RECORD)
|
if (card->debug_flags & LOG_POF_RECORD)
|
||||||
hysdn_addlog(card, "ERGO: pof boot success");
|
hysdn_addlog(card, "ERGO: pof boot success");
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli();
|
|
||||||
|
|
||||||
card->state = CARD_STATE_RUN; /* now card is running */
|
card->state = CARD_STATE_RUN; /* now card is running */
|
||||||
/* enable the cards interrupt */
|
/* enable the cards interrupt */
|
||||||
byteout(card->iobase + PCI9050_INTR_REG,
|
byteout(card->iobase + PCI9050_INTR_REG,
|
||||||
|
@ -385,8 +369,7 @@ ergo_waitpofready(struct HYSDN_CARD *card)
|
||||||
dpr->ToPcFlag = 0; /* reset data indicator */
|
dpr->ToPcFlag = 0; /* reset data indicator */
|
||||||
dpr->ToHyInt = 1;
|
dpr->ToHyInt = 1;
|
||||||
dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
|
dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
|
||||||
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
restore_flags(flags);
|
|
||||||
if ((hynet_enable & (1 << card->myid))
|
if ((hynet_enable & (1 << card->myid))
|
||||||
&& (i = hysdn_net_create(card)))
|
&& (i = hysdn_net_create(card)))
|
||||||
{
|
{
|
||||||
|
@ -401,7 +384,6 @@ ergo_waitpofready(struct HYSDN_CARD *card)
|
||||||
#endif /* CONFIG_HYSDN_CAPI */
|
#endif /* CONFIG_HYSDN_CAPI */
|
||||||
return (0); /* success */
|
return (0); /* success */
|
||||||
} /* data has arrived */
|
} /* data has arrived */
|
||||||
sti();
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
schedule_timeout((50 * HZ) / 1000); /* Timeout 50ms */
|
schedule_timeout((50 * HZ) / 1000); /* Timeout 50ms */
|
||||||
} /* wait until timeout */
|
} /* wait until timeout */
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
#include <linux/tqueue.h>
|
#include <linux/tqueue.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/isdn_compat.h>
|
#include <linux/isdn_compat.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
|
#define HYSDN_SPIN_LOCK(a,b) spin_lock(a)
|
||||||
|
#define HYSDN_SPIN_UNLOCK(a,b) spin_unlock(a)
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* storage type definitions */
|
/* storage type definitions */
|
||||||
|
|
|
@ -128,8 +128,7 @@ put_log_buffer(hysdn_card * card, char *cp)
|
||||||
strcpy(ib->log_start, cp); /* set output string */
|
strcpy(ib->log_start, cp); /* set output string */
|
||||||
ib->next = NULL;
|
ib->next = NULL;
|
||||||
ib->proc_ctrl = pd; /* point to own control structure */
|
ib->proc_ctrl = pd; /* point to own control structure */
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli();
|
|
||||||
ib->usage_cnt = pd->if_used;
|
ib->usage_cnt = pd->if_used;
|
||||||
if (!pd->log_head)
|
if (!pd->log_head)
|
||||||
pd->log_head = ib; /* new head */
|
pd->log_head = ib; /* new head */
|
||||||
|
@ -137,7 +136,7 @@ put_log_buffer(hysdn_card * card, char *cp)
|
||||||
pd->log_tail->next = ib; /* follows existing messages */
|
pd->log_tail->next = ib; /* follows existing messages */
|
||||||
pd->log_tail = ib; /* new tail */
|
pd->log_tail = ib; /* new tail */
|
||||||
i = pd->del_lock++; /* get lock state */
|
i = pd->del_lock++; /* get lock state */
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
|
|
||||||
/* delete old entrys */
|
/* delete old entrys */
|
||||||
if (!i)
|
if (!i)
|
||||||
|
@ -294,14 +293,13 @@ hysdn_log_open(struct inode *ino, struct file *filep)
|
||||||
} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
|
} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
|
||||||
|
|
||||||
/* read access -> log/debug read */
|
/* read access -> log/debug read */
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli();
|
|
||||||
pd->if_used++;
|
pd->if_used++;
|
||||||
if (pd->log_head)
|
if (pd->log_head)
|
||||||
(struct log_data **) filep->private_data = &(pd->log_tail->next);
|
(struct log_data **) filep->private_data = &(pd->log_tail->next);
|
||||||
else
|
else
|
||||||
(struct log_data **) filep->private_data = &(pd->log_head);
|
(struct log_data **) filep->private_data = &(pd->log_head);
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
} else { /* simultaneous read/write access forbidden ! */
|
} else { /* simultaneous read/write access forbidden ! */
|
||||||
#ifdef COMPAT_USE_MODCOUNT_LOCK
|
#ifdef COMPAT_USE_MODCOUNT_LOCK
|
||||||
MOD_DEC_USE_COUNT;
|
MOD_DEC_USE_COUNT;
|
||||||
|
@ -342,8 +340,7 @@ hysdn_log_close(struct inode *ino, struct file *filep)
|
||||||
/* read access -> log/debug read, mark one further file as closed */
|
/* read access -> log/debug read, mark one further file as closed */
|
||||||
|
|
||||||
pd = NULL;
|
pd = NULL;
|
||||||
save_flags(flags);
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
cli();
|
|
||||||
inf = *((struct log_data **) filep->private_data); /* get first log entry */
|
inf = *((struct log_data **) filep->private_data); /* get first log entry */
|
||||||
if (inf)
|
if (inf)
|
||||||
pd = (struct procdata *) inf->proc_ctrl; /* still entries there */
|
pd = (struct procdata *) inf->proc_ctrl; /* still entries there */
|
||||||
|
@ -366,7 +363,7 @@ hysdn_log_close(struct inode *ino, struct file *filep)
|
||||||
inf->usage_cnt--; /* decrement usage count for buffers */
|
inf->usage_cnt--; /* decrement usage count for buffers */
|
||||||
inf = inf->next;
|
inf = inf->next;
|
||||||
}
|
}
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
|
|
||||||
if (pd)
|
if (pd)
|
||||||
if (pd->if_used <= 0) /* delete buffers if last file closed */
|
if (pd->if_used <= 0) /* delete buffers if last file closed */
|
||||||
|
|
|
@ -164,22 +164,19 @@ hysdn_tx_cfgline(hysdn_card * card, uchar * line, word 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);
|
||||||
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
save_flags(flags);
|
|
||||||
cli();
|
|
||||||
while (card->async_busy) {
|
while (card->async_busy) {
|
||||||
sti();
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
|
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
|
||||||
if (!--cnt) {
|
if (!--cnt) {
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
return (-ERR_ASYNC_TIME); /* timed out */
|
return (-ERR_ASYNC_TIME); /* timed out */
|
||||||
}
|
}
|
||||||
cli();
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
} /* wait for buffer to become free */
|
} /* wait for buffer to become free */
|
||||||
|
|
||||||
strcpy(card->async_data, line);
|
strcpy(card->async_data, line);
|
||||||
|
@ -190,31 +187,26 @@ hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan)
|
||||||
/* now queue the task */
|
/* now queue the task */
|
||||||
queue_task(&card->irq_queue, &tq_immediate);
|
queue_task(&card->irq_queue, &tq_immediate);
|
||||||
mark_bh(IMMEDIATE_BH);
|
mark_bh(IMMEDIATE_BH);
|
||||||
sti();
|
HYSDN_SPIN_UNLOCK(&card->irq_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();
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
|
|
||||||
while (card->async_busy) {
|
while (card->async_busy) {
|
||||||
sti();
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
|
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
|
||||||
if (!--cnt) {
|
if (!--cnt) {
|
||||||
restore_flags(flags);
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
return (-ERR_ASYNC_TIME); /* timed out */
|
return (-ERR_ASYNC_TIME); /* timed out */
|
||||||
}
|
}
|
||||||
cli();
|
HYSDN_SPIN_LOCK(&card->irq_lock, flags);
|
||||||
} /* wait for buffer to become free again */
|
} /* wait for buffer to become free again */
|
||||||
|
HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
|
||||||
restore_flags(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");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue