summaryrefslogtreecommitdiff
path: root/zaptel.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-02-06 21:13:14 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-02-06 21:13:14 +0000
commit839b5172e6bb6c2dcb0ba0eb5ae6ae631af746ff (patch)
treef5415e24d91fdb789c9dc814dec58b3afb6e215e /zaptel.c
parent5377e38362656507d448ea811813a971f1509443 (diff)
Clear pseudos at end of interrupt handler ONLY
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@308 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rwxr-xr-xzaptel.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/zaptel.c b/zaptel.c
index e6380d4..a2206c7 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -296,6 +296,10 @@ static struct zt_timer {
static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED;
+static spinlock_t zapfreelock = SPIN_LOCK_UNLOCKED;
+
+static int zapneedfree = 0;
+
struct zt_zone {
char name[40]; /* Informational, only */
int ringcadence[ZT_MAX_CADENCE];
@@ -1458,6 +1462,17 @@ static struct ppp_channel_ops ztppp_ops =
};
#endif
+
+static void __zt_recalc_maxchans(void)
+{
+ int x;
+ maxchans = 0;
+ for (x=1;x<ZT_MAX_CHANNELS;x++)
+ if (chans[x]) {
+ maxchans = x + 1;
+ }
+}
+
static void zt_chan_unreg(struct zt_chan *chan)
{
int x;
@@ -2064,6 +2079,8 @@ static int zt_specchan_open(struct inode *inode, struct file *file, int unit, in
/* Make sure we're not already open, a net device, or a slave device */
if (chans[unit]->flags & ZT_FLAG_OPEN)
res = -EBUSY;
+ else if (chans[unit]->flags & ZT_FLAG_DEAD)
+ res = -EBUSY;
else if (chans[unit]->flags & ZT_FLAG_NETDEV)
res = -EBUSY;
else if (chans[unit]->master != chans[unit])
@@ -2131,7 +2148,7 @@ static struct zt_chan *zt_alloc_pseudo(void)
return pseudo;
}
-static void zt_free_pseudo(struct zt_chan *pseudo)
+static void __zt_free_pseudo(struct zt_chan *pseudo)
{
if (pseudo) {
zt_chan_unreg(pseudo);
@@ -2139,6 +2156,18 @@ static void zt_free_pseudo(struct zt_chan *pseudo)
}
}
+static void zt_free_pseudo(struct zt_chan *pseudo)
+{
+ long flags;
+ if (pseudo) {
+ /* Mark as dead for later reaping */
+ pseudo->flags |= ZT_FLAG_DEAD;
+ spin_lock_irqsave(&zapfreelock, flags);
+ zapneedfree = 1;
+ spin_unlock_irqrestore(&zapfreelock, flags);
+ }
+}
+
static int zt_open(struct inode *inode, struct file *file)
{
int unit = UNIT(file);
@@ -5845,6 +5874,18 @@ int zt_receive(struct zt_span *span)
spin_unlock_irqrestore(&chans[x]->lock, flags);
}
}
+ spin_lock_irqsave(&zapfreelock, flags);
+ if (zapneedfree) {
+ /* Free any pseudos that might need it */
+ for (x=0;x<maxchans;x++) {
+ if (chans[x] && (chans[x]->flags & ZT_FLAG_DEAD)) {
+ __zt_free_pseudo(chans[x]);
+ }
+ }
+ }
+ __zt_recalc_maxchans();
+ spin_unlock_irqrestore(&zapfreelock, flags);
+
}
#endif
return 0;