--- zaptel.c 2007-03-30 14:43:36.887672500 +0300 +++ zaptel.patched.c 2007-03-30 14:59:23.897582900 +0300 @@ -793,7 +793,6 @@ static int zt_reallocbufs(struct zt_chan *ss, int j, int numbufs) { unsigned char *newbuf, *oldbuf; - unsigned long flags; int x; /* Check numbufs */ if (numbufs < 2) @@ -802,14 +801,13 @@ numbufs = ZT_MAX_NUM_BUFS; /* We need to allocate our buffers now */ if (j) { - newbuf = kmalloc(j * 2 * numbufs, GFP_KERNEL); + newbuf = kmalloc(j * 2 * numbufs, GFP_ATOMIC); if (!newbuf) return (-ENOMEM); } else newbuf = NULL; /* Now that we've allocated our new buffer, we can safely move things around... */ - spin_lock_irqsave(&ss->lock, flags); ss->blocksize = j; /* set the blocksize */ oldbuf = ss->readbuf[0]; /* Keep track of the old buffer */ ss->readbuf[0] = NULL; @@ -853,7 +851,6 @@ else ss->rxdisable = 0; - spin_unlock_irqrestore(&ss->lock, flags); if (oldbuf) kfree(oldbuf); return 0; @@ -988,9 +985,9 @@ #endif /* XXX Buffers should be send out before reallocation!!! XXX */ + spin_lock_irqsave(&chan->lock, flags); if (!(chan->flags & ZT_FLAG_NOSTDTXRX)) zt_reallocbufs(chan, 0, 0); - spin_lock_irqsave(&chan->lock, flags); #ifdef CONFIG_ZAPATA_PPP ppp = chan->ppp; chan->ppp = NULL; @@ -1325,6 +1322,7 @@ { struct zt_chan *ms = hdlc_to_ztchan(hdlc); int res; + unsigned long flags; #endif if (!ms) { printk("zt_net_open: nothing??\n"); @@ -1341,7 +1339,9 @@ ms->txbufpolicy = ZT_POLICY_IMMEDIATE; ms->rxbufpolicy = ZT_POLICY_IMMEDIATE; + spin_lock_irqsave(&ms->lock, flags); res = zt_reallocbufs(ms, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS); + spin_unlock_irqrestore(&ms->lock, flags); if (res) return res; @@ -1395,6 +1395,7 @@ { #endif struct zt_chan *ms = hdlc_to_ztchan(hdlc); + unsigned long flags; if (!ms) { #ifdef NEW_HDLC_INTERFACE printk("zt_net_stop: nothing??\n"); @@ -1415,7 +1416,9 @@ } /* Not much to do here. Just deallocate the buffers */ netif_stop_queue(ztchan_to_dev(ms)); + spin_lock_irqsave(&ms->lock, flags); zt_reallocbufs(ms, 0, 0); + spin_unlock_irqrestore(&ms->lock, flags); #ifdef LINUX26 hdlc_close(dev); #else @@ -2157,17 +2160,14 @@ return res; } -static int initialize_channel(struct zt_chan *chan) +static int inline initialize_channel(struct zt_chan *chan) { int res; - unsigned long flags; void *rxgain=NULL; struct echo_can_state *ec=NULL; if ((res = zt_reallocbufs(chan, ZT_DEFAULT_BLOCKSIZE, ZT_DEFAULT_NUM_BUFS))) return res; - spin_lock_irqsave(&chan->lock, flags); - chan->rxbufpolicy = ZT_POLICY_IMMEDIATE; chan->txbufpolicy = ZT_POLICY_IMMEDIATE; @@ -2272,7 +2272,6 @@ } if (chan->span && chan->span->echocan) chan->span->echocan(chan, 0); - spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) kfree(rxgain); @@ -2342,9 +2341,7 @@ if (chans[unit] && chans[unit]->sig) { /* 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_NETDEV) + if (chans[unit]->flags & ZT_FLAG_NETDEV) res = -EBUSY; else if (chans[unit]->master != chans[unit]) res = -EBUSY; @@ -2352,9 +2349,13 @@ res = -EBUSY; else { unsigned long flags; + spin_lock_irqsave(&chans[unit]->lock, flags); + if (chans[unit]->flags & ZT_FLAG_OPEN) { + spin_unlock_irqrestore(&chans[unit]->lock, flags); + return -EBUSY; + } /* Assume everything is going to be okay */ res = initialize_channel(chans[unit]); - spin_lock_irqsave(&chans[unit]->lock, flags); if (chans[unit]->flags & ZT_FLAG_PSEUDO) chans[unit]->flags |= ZT_FLAG_AUDIO; if (chans[unit]->span && chans[unit]->span->open) @@ -3720,8 +3721,12 @@ return -EINVAL; chan->rxbufpolicy = stack.bi.rxbufpolicy & 0x1; chan->txbufpolicy = stack.bi.txbufpolicy & 0x1; - if ((rv = zt_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) + spin_lock_irqsave(&chan->lock, flags); + if ((rv = zt_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) { + spin_unlock_irqrestore(&chan->lock, flags); return (rv); + } + spin_unlock_irqrestore(&chan->lock, flags); break; case ZT_GET_BLOCKSIZE: /* get blocksize */ put_user(chan->blocksize,(int *)data); /* return block size */ @@ -3732,10 +3737,14 @@ if (j > ZT_MAX_BLOCKSIZE) return(-EINVAL); /* cannot be less then 16 */ if (j < 16) return(-EINVAL); + spin_lock_irqsave(&chan->lock, flags); /* allocate a single kernel buffer which we then sub divide into four pieces */ - if ((rv = zt_reallocbufs(chan, j, chan->numbufs))) + if ((rv = zt_reallocbufs(chan, j, chan->numbufs))) { + spin_unlock_irqrestore(&chan->lock, flags); return (rv); + } + spin_unlock_irqrestore(&chan->lock, flags); break; case ZT_FLUSH: /* flush input buffer, output buffer, and/or event queue */ get_user(i,(int *)data); /* get param */ @@ -4268,12 +4277,14 @@ chan->do_ppp_wakeup = 0; tasklet_init(&chan->ppp_calls, do_ppp_calls, (unsigned long)chan); + spin_lock_irqsave(&chan->lock, flags); if ((ret = zt_reallocbufs(chan, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS))) { + spin_unlock_irqrestore(&chan->lock, flags); kfree(chan->ppp); chan->ppp = NULL; return ret; } - + spin_unlock_irqrestore(&chan->lock, flags); if ((ret = ppp_register_channel(chan->ppp))) { kfree(chan->ppp); chan->ppp = NULL;