--- zaptel.c 2007-04-04 13:45:07.049356500 +0300 +++ zaptel.patch.c 2007-04-05 09:35:07.918393600 +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; @@ -987,10 +984,10 @@ struct ppp_channel *ppp; #endif + spin_lock_irqsave(&chan->lock, flags); /* XXX Buffers should be send out before reallocation!!! XXX */ 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; @@ -1308,6 +1305,7 @@ #ifdef NEW_HDLC_INTERFACE static int zt_net_open(struct net_device *dev) { + unsigned long flags; #ifdef LINUX26 int res = hdlc_open(dev); struct zt_chan *ms = dev_to_ztchan(dev); @@ -1316,7 +1314,6 @@ struct zt_chan *ms = hdlc_to_ztchan(hdlc); int res = hdlc_open(hdlc); #endif - /* if (!dev->hard_start_xmit) return res; is this really necessary? --byg */ if (res) /* this is necessary to avoid kernel panic when UNSPEC link encap, proven --byg */ return res; @@ -1325,16 +1322,20 @@ { struct zt_chan *ms = hdlc_to_ztchan(hdlc); int res; + unsigned long flags; #endif if (!ms) { printk("zt_net_open: nothing??\n"); return -EINVAL; } + spin_lock_irqsave(&ms->lock, flags); if (ms->flags & ZT_FLAG_OPEN) { + spin_unlock_irqrestore(&ms->lock, flags); printk("%s is already open!\n", ms->name); return -EBUSY; } if (!(ms->flags & ZT_FLAG_NETDEV)) { + spin_unlock_irqrestore(&ms->lock, flags); printk("%s is not a net device!\n", ms->name); return -EINVAL; } @@ -1342,18 +1343,19 @@ ms->rxbufpolicy = ZT_POLICY_IMMEDIATE; res = zt_reallocbufs(ms, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS); - if (res) + if (res) { + spin_unlock_irqrestore(&ms->lock, flags); return res; - + } fasthdlc_init(&ms->rxhdlc); fasthdlc_init(&ms->txhdlc); ms->infcs = PPP_INITFCS; - netif_start_queue(ztchan_to_dev(ms)); - + spin_unlock_irqrestore(&ms->lock, flags); #ifndef LINUX26 MOD_INC_USE_COUNT; #endif + #ifdef CONFIG_ZAPATA_DEBUG printk("ZAPNET: Opened channel %d name %s\n", ms->channo, ms->name); #endif @@ -1395,6 +1397,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"); @@ -1404,7 +1407,9 @@ return; #endif } + spin_lock_irqsave(&ms->lock, flags); if (!(ms->flags & ZT_FLAG_NETDEV)) { + spin_unlock_irqrestore(&ms->lock, flags); #ifdef NEW_HDLC_INTERFACE printk("zt_net_stop: %s is not a net device!\n", ms->name); return 0; @@ -1414,8 +1419,9 @@ #endif } /* Not much to do here. Just deallocate the buffers */ - netif_stop_queue(ztchan_to_dev(ms)); + netif_stop_queue(ztchan_to_dev(ms)); zt_reallocbufs(ms, 0, 0); + spin_unlock_irqrestore(&ms->lock, flags); #ifdef LINUX26 hdlc_close(dev); #else @@ -2157,17 +2163,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 +2275,6 @@ } if (chan->span && chan->span->echocan) chan->span->echocan(chan, 0); - spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) kfree(rxgain); @@ -2340,9 +2342,13 @@ { int res = 0; - if (chans[unit] && chans[unit]->sig) { + if (chans[unit]) { + unsigned long flags; + spin_lock_irqsave(&chans[unit]->lock, flags); + if (!chans[unit]->sig) + res = -ENXIO; /* Make sure we're not already open, a net device, or a slave device */ - if (chans[unit]->flags & ZT_FLAG_OPEN) + else if (chans[unit]->flags & ZT_FLAG_OPEN) res = -EBUSY; else if (chans[unit]->flags & ZT_FLAG_NETDEV) res = -EBUSY; @@ -2351,10 +2357,11 @@ else if ((chans[unit]->sig & __ZT_SIG_DACS) == __ZT_SIG_DACS) res = -EBUSY; else { - unsigned long flags; - /* Assume everything is going to be okay */ res = initialize_channel(chans[unit]); - spin_lock_irqsave(&chans[unit]->lock, flags); + if (res) { + spin_unlock_irqrestore(&chans[unit]->lock, flags); + return res; + } if (chans[unit]->flags & ZT_FLAG_PSEUDO) chans[unit]->flags |= ZT_FLAG_AUDIO; if (chans[unit]->span && chans[unit]->span->open) @@ -2366,12 +2373,13 @@ MOD_INC_USE_COUNT; #endif chans[unit]->flags |= ZT_FLAG_OPEN; - spin_unlock_irqrestore(&chans[unit]->lock, flags); } else { spin_unlock_irqrestore(&chans[unit]->lock, flags); close_channel(chans[unit]); - } + return res; + } } + spin_unlock_irqrestore(&chans[unit]->lock, flags); } else res = -ENXIO; return res; @@ -2384,8 +2392,8 @@ unsigned long flags; spin_lock_irqsave(&chans[unit]->lock, flags); chans[unit]->flags &= ~ZT_FLAG_OPEN; - spin_unlock_irqrestore(&chans[unit]->lock, flags); chans[unit]->file = NULL; + spin_unlock_irqrestore(&chans[unit]->lock, flags); close_channel(chans[unit]); if (chans[unit]->span && chans[unit]->span->close) res = chans[unit]->span->close(chans[unit]); @@ -3721,10 +3729,14 @@ return -EINVAL; if (stack.bi.bufsize * stack.bi.numbufs > ZT_MAX_BUF_SPACE) return -EINVAL; + spin_lock_irqsave(&chan->lock, flags); chan->rxbufpolicy = stack.bi.rxbufpolicy & 0x1; chan->txbufpolicy = stack.bi.txbufpolicy & 0x1; - if ((rv = zt_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) + 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 */ @@ -3735,10 +3747,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 */ @@ -4256,11 +4272,15 @@ break; case ZT_HDLCPPP: #ifdef CONFIG_ZAPATA_PPP - if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); get_user(j, (int *)data); + spin_lock_irqsave(&chan->lock, flags); + if (chan->sig != ZT_SIG_CLEAR) { + spin_unlock_irqrestore(&chan->lock, flags); + return (-EINVAL); + } if (j) { if (!chan->ppp) { - chan->ppp = kmalloc(sizeof(struct ppp_channel), GFP_KERNEL); + chan->ppp = kmalloc(sizeof(struct ppp_channel), GFP_ATOMIC); if (chan->ppp) { memset(chan->ppp, 0, sizeof(struct ppp_channel)); chan->ppp->private = chan; @@ -4274,14 +4294,18 @@ if ((ret = zt_reallocbufs(chan, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS))) { kfree(chan->ppp); chan->ppp = NULL; + spin_unlock_irqrestore(&chan->lock, flags); return ret; } - + spin_unlock_irqrestore(&chan->lock, flags); if ((ret = ppp_register_channel(chan->ppp))) { + spin_lock_irqsave(&chan->lock, flags); kfree(chan->ppp); chan->ppp = NULL; + spin_unlock_irqrestore(&chan->lock, flags); return ret; } + spin_lock_irqsave(&chan->lock, flags); tec = chan->ec; chan->ec = NULL; chan->echocancel = 0; @@ -4298,22 +4322,28 @@ chan->flags |= (ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); if (chan->span && chan->span->echocan) chan->span->echocan(chan, 0); + spin_unlock_irqrestore(&chan->lock, flags); if (tec) echo_can_free(tec); - } else + } else { + spin_unlock_irqrestore(&chan->lock, flags); return -ENOMEM; + } + } else { + spin_unlock_irqrestore(&chan->lock, flags); } - } else { + } else if (chan->flags & ZT_FLAG_PPP) { + struct ppp_channel *ppp = chan->ppp; + chan->ppp = NULL; chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); - if (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); - } - } + spin_unlock_irqrestore(&chan->lock, flags); + tasklet_kill(&chan->ppp_calls); + skb_queue_purge(&chan->ppp_rq); + ppp_unregister_channel(ppp); + kfree(ppp); + } else { + spin_unlock_irqrestore(&chan->lock, flags); + } #else printk("Zaptel: Zaptel PPP support not compiled in\n"); return -ENOSYS;