diff options
Diffstat (limited to 'zaptel.c')
-rwxr-xr-x | zaptel.c | 91 |
1 files changed, 68 insertions, 23 deletions
@@ -800,7 +800,7 @@ static void reset_conf(struct zt_chan *chan) static void close_channel(struct zt_chan *chan) { - unsigned int flags; + unsigned long flags; void *rxgain = NULL; echo_can_state_t *ec = NULL; int oldconf; @@ -871,6 +871,8 @@ static void close_channel(struct zt_chan *chan) #ifdef CONFIG_ZAPATA_PPP if (ppp) { + tasklet_kill(&chan->ppp_calls); + skb_queue_purge(&chan->ppp_rq); ppp_unregister_channel(ppp); kfree(ppp); } @@ -1040,7 +1042,7 @@ static int zt_chan_reg(struct zt_chan *chan) { int x; int res=0; - unsigned int flags; + unsigned long flags; write_lock_irqsave(&chan_lock, flags); for (x=1;x<ZT_MAX_CHANNELS;x++) { @@ -1293,7 +1295,9 @@ static int zt_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb) spin_unlock_irqrestore(&ss->lock, flags); if (retval) { /* Get rid of the SKB if we're returning non-zero */ - dev_kfree_skb_any(skb); + /* N.B. this is called in process or BH context so + dev_kfree_skb is OK. */ + dev_kfree_skb(skb); } return retval; } @@ -1313,7 +1317,7 @@ static struct ppp_channel_ops ztppp_ops = static void zt_chan_unreg(struct zt_chan *chan) { int x; - unsigned int flags; + unsigned long flags; write_lock_irqsave(&chan_lock, flags); if (chan->flags & ZT_FLAG_REGISTERED) { chans[chan->channo] = NULL; @@ -1362,7 +1366,7 @@ static ssize_t zt_chan_read(struct file *file, char *usrbuf, size_t count, int u int amnt; int res, rv; int oldbuf,x; - unsigned int flags; + unsigned long flags; if (!chan) return -EINVAL; if (count < 1) @@ -1436,7 +1440,7 @@ static ssize_t zt_chan_read(struct file *file, char *usrbuf, size_t count, int u static ssize_t zt_chan_write(struct file *file, const char *usrbuf, size_t count, int unit) { - unsigned int flags; + unsigned long flags; struct zt_chan *chan = chans[unit]; int res, amnt, oldbuf, rv,x; if (!chan) @@ -1688,7 +1692,7 @@ static int zt_hangup(struct zt_chan *chan) static int initialize_channel(struct zt_chan *chan) { int res; - unsigned int flags; + unsigned long flags; void *rxgain=NULL; echo_can_state_t *ec=NULL; if ((res = zt_reallocbufs(chan, ZT_DEFAULT_BLOCKSIZE, ZT_DEFAULT_NUM_BUFS))) @@ -2216,7 +2220,7 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c struct zt_chan *chan,mychan; int i,j; struct zt_params param; - unsigned int flags; + unsigned long flags; switch(cmd) { case ZT_GET_PARAMS: /* get channel timing parameters */ @@ -2490,7 +2494,7 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct zt_chan *newmaster; struct zt_dialparams tdp; struct zt_maintinfo maint; - unsigned int flags; + unsigned long flags; int rv; switch(cmd) { @@ -2763,7 +2767,7 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign struct zt_bufferinfo bi; struct zt_confinfo conf; struct zt_ring_cadence cad; - unsigned int flags; + unsigned long flags; int i, j, k, rv; int ret, c; @@ -3205,10 +3209,37 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign return 0; } +#ifdef CONFIG_ZAPATA_PPP +/* + * This is called at softirq (BH) level when there are calls + * we need to make to the ppp_generic layer. We do it this + * way because the ppp_generic layer functions may not be called + * at interrupt level. + */ +static void do_ppp_calls(unsigned long data) +{ + struct zt_chan *chan = (struct zt_chan *) data; + struct sk_buff *skb; + + if (!chan->ppp) + return; + if (chan->do_ppp_wakeup) { + chan->do_ppp_wakeup = 0; + ppp_output_wakeup(chan->ppp); + } + while ((skb = skb_dequeue(&chan->ppp_rq)) != NULL) + ppp_input(chan->ppp, skb); + if (chan->do_ppp_error) { + chan->do_ppp_error = 0; + ppp_input_error(chan->ppp, 0); + } +} +#endif + static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) { struct zt_chan *chan = chans[unit]; - unsigned int flags; + unsigned long flags; int j, rv; int ret; echo_can_state_t *ec, *tec; @@ -3241,6 +3272,10 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm chan->ppp->ops = &ztppp_ops; chan->ppp->mtu = ZT_DEFAULT_MTU_MRU; chan->ppp->hdrlen = 0; + skb_queue_head_init(&chan->ppp_rq); + chan->do_ppp_wakeup = 0; + tasklet_init(&chan->ppp_calls, do_ppp_calls, + (unsigned long)chan); if ((ret = zt_reallocbufs(chan, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS))) { kfree(chan->ppp); chan->ppp = NULL; @@ -3271,9 +3306,12 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm } else { chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); if (chan->ppp) { - ppp_unregister_channel(chan->ppp); - kfree(chan->ppp); + struct ppp_channel *ppp = chan->ppp; chan->ppp = NULL; + tasklet_kill(&chan->ppp_calls); + skb_queue_purge(&chan->ppp_rq); + ppp_unregister_channel(ppp); + kfree(ppp); } } #else @@ -4018,7 +4056,8 @@ out in the later versions, and is put back now. */ #endif #ifdef CONFIG_ZAPATA_PPP if (ms->flags & ZT_FLAG_PPP) { - ppp_output_wakeup(ms->ppp); + ms->do_ppp_wakeup = 1; + tasklet_schedule(&ms->ppp_calls); } #endif } @@ -4658,7 +4697,10 @@ static inline void zt_putbuf_chunk(struct zt_chan *ss, unsigned char *rxb) /* Drop the FCS */ ms->readn[ms->inreadbuf] -= 2; /* Allocate an SKB */ - skb = dev_alloc_skb(ms->readn[ms->inreadbuf]); +#ifdef CONFIG_ZAPATA_PPP + if (!ms->do_ppp_error) +#endif + skb = dev_alloc_skb(ms->readn[ms->inreadbuf]); if (skb) { /* XXX Get rid of this memcpy XXX */ memcpy(skb->data, ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf]); @@ -4670,14 +4712,14 @@ static inline void zt_putbuf_chunk(struct zt_chan *ss, unsigned char *rxb) #endif #ifdef CONFIG_ZAPATA_PPP if (ms->flags & ZT_FLAG_PPP) { - printk("Would call ppp_input_error\n"); -#if 1 - ppp_input_error(ms->ppp, 0); -#endif + abort = ZT_EVENT_OVERRUN; } #endif #if 1 - printk("Memory squeeze, dropped one\n"); +#ifdef CONFIG_ZAPATA_PPP + if (!ms->do_ppp_error) +#endif + printk("Memory squeeze, dropped one\n"); #endif } } @@ -4744,7 +4786,8 @@ out in the later versions, and is put back now. */ #endif #ifdef CONFIG_ZAPATA_PPP if (ms->flags & ZT_FLAG_PPP) { - ppp_input_error(ms->ppp, 0); + ms->do_ppp_error = 1; + tasklet_schedule(&ms->ppp_calls); } else #endif @@ -4773,8 +4816,10 @@ out in the later versions, and is put back now. */ if (tmp) printk("Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]); dev_kfree_skb_irq(skb); - } else - ppp_input(ms->ppp, skb); + } else { + skb_queue_tail(&ms->ppp_rq, skb); + tasklet_schedule(&ms->ppp_calls); + } } #endif } |