Index: zaptel.c =================================================================== --- zaptel.c (revision 2289) +++ zaptel.c (working copy) @@ -769,16 +769,19 @@ if (!signal_pending(current)) schedule(); current->state = TASK_RUNNING; remove_wait_queue(q, &wait); - if (signal_pending(current)) return -ERESTARTSYS; + if (signal_pending(current)) { + printk(KERN_WARNING "zaptel.c:%d (pid %d: %s) got signal %08lX\n", __LINE__, current->pid, current->comm, current->pending.signal.sig[0]); + return -ERESTARTSYS; + } return(0); } -static inline void calc_fcs(struct zt_chan *ss) +static inline void calc_fcs(struct zt_chan *ss, int inwritebuf) { int x; unsigned int fcs=PPP_INITFCS; - unsigned char *data = ss->writebuf[ss->inwritebuf]; - int len = ss->writen[ss->inwritebuf]; + unsigned char *data = ss->writebuf[inwritebuf]; + int len = ss->writen[inwritebuf]; /* Not enough space to do FCS calculation */ if (len < 2) return; @@ -1765,8 +1768,8 @@ if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { int myamnt = amnt; int x; - if (amnt > chan->readn[chan->outreadbuf]) - myamnt = chan->readn[chan->outreadbuf]; + if (amnt > chan->readn[res]) + myamnt = chan->readn[res]; printk("zt_chan_read(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", unit, chan->inwritebuf, chan->outwritebuf, myamnt); printk("\t("); for (x = 0; x < myamnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); @@ -1775,8 +1778,8 @@ #endif /* end addition */ if (chan->flags & ZT_FLAG_LINEAR) { - if (amnt > (chan->readn[chan->outreadbuf] << 1)) - amnt = chan->readn[chan->outreadbuf] << 1; + if (amnt > (chan->readn[res] << 1)) + amnt = chan->readn[res] << 1; if (amnt) { /* There seems to be a max stack size, so we have to do this in smaller pieces */ @@ -1789,7 +1792,7 @@ if (pass > 128) pass = 128; for (x=0;xreadbuf[chan->outreadbuf][x + pos], chan); + lindata[x] = ZT_XLAW(chan->readbuf[res][x + pos], chan); if (copy_to_user(usrbuf + (pos << 1), lindata, pass << 1)) return -EFAULT; left -= pass; @@ -1797,18 +1800,18 @@ } } } else { - if (amnt > chan->readn[chan->outreadbuf]) - amnt = chan->readn[chan->outreadbuf]; + if (amnt > chan->readn[res]) + amnt = chan->readn[res]; if (amnt) { - if (copy_to_user(usrbuf, chan->readbuf[chan->outreadbuf], amnt)) + if (copy_to_user(usrbuf, chan->readbuf[res], amnt)) return -EFAULT; } } spin_lock_irqsave(&chan->lock, flags); - chan->readidx[chan->outreadbuf] = 0; - chan->readn[chan->outreadbuf] = 0; - oldbuf = chan->outreadbuf; - chan->outreadbuf = (chan->outreadbuf + 1) % chan->numbufs; + chan->readidx[res] = 0; + chan->readn[res] = 0; + oldbuf = res; + res = (chan->outreadbuf + 1) % chan->numbufs; if (chan->outreadbuf == chan->inreadbuf) { /* Out of stuff */ chan->outreadbuf = -1; @@ -1870,14 +1873,14 @@ } #ifdef CONFIG_ZAPATA_DEBUG - printk("zt_chan_write(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", - unit, chan->inwritebuf, chan->outwritebuf, amnt); + printk("zt_chan_write(unit: %d, res: %d, outwritebuf: %d amnt: %d\n", + unit, chan->res, chan->outwritebuf, amnt); #endif #if 0 if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { int x; - printk("zt_chan_write/in(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d, txdisable: %d)\n", - unit, chan->inwritebuf, chan->outwritebuf, amnt, chan->txdisable); + printk("zt_chan_write/in(unit: %d, res: %d, outwritebuf: %d amnt: %d, txdisable: %d)\n", + unit, res, chan->outwritebuf, amnt, chan->txdisable); printk("\t("); for (x = 0; x < amnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); printk(")\n"); } @@ -1899,21 +1902,21 @@ return -EFAULT; left -= pass; for (x=0;xwritebuf[chan->inwritebuf][x + pos] = ZT_LIN2X(lindata[x], chan); + chan->writebuf[res][x + pos] = ZT_LIN2X(lindata[x], chan); pos += pass; } - chan->writen[chan->inwritebuf] = amnt >> 1; + chan->writen[res] = amnt >> 1; } else { - if (copy_from_user(chan->writebuf[chan->inwritebuf], usrbuf, amnt)) + if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) return -EFAULT; - chan->writen[chan->inwritebuf] = amnt; + chan->writen[res] = amnt; } - chan->writeidx[chan->inwritebuf] = 0; + chan->writeidx[res] = 0; if (chan->flags & ZT_FLAG_FCS) - calc_fcs(chan); - oldbuf = chan->inwritebuf; + calc_fcs(chan, res); + oldbuf = res; spin_lock_irqsave(&chan->lock, flags); - chan->inwritebuf = (chan->inwritebuf + 1) % chan->numbufs; + chan->inwritebuf = (res + 1) % chan->numbufs; if (chan->inwritebuf == chan->outwritebuf) { /* Don't stomp on the transmitter, just wait for them to wake us up */ @@ -2097,6 +2100,7 @@ static int zt_hangup(struct zt_chan *chan) { + /* Called with spin_lock_irqsave(&chan->lock, flags); held */ int x,res=0; /* Can't hangup pseudo channels */ @@ -2943,10 +2947,6 @@ struct zt_chan *chan; unsigned long flags; unsigned char *txgain, *rxgain; -#ifdef ALLOW_CHAN_DIAG - /* This structure is huge and will bork a 4k stack */ - struct zt_chan mychan; -#endif int i,j; int return_master = 0; @@ -3156,57 +3156,68 @@ if (copy_to_user((struct zt_spaninfo *) data,&stack.span,sizeof(stack.span))) return -EFAULT; break; -#ifdef ALLOW_CHAN_DIAG case ZT_CHANDIAG: + { + /* Instead of putting the large zt_chan structure onto the stack + * it is now allocated only when it's needed using kmalloc(). + * So this IOCTL can now stay enabled permanently. + */ + struct zt_chan* mychan = NULL; + unsigned long flags = 0; get_user(j, (int *)data); /* get channel number from user */ /* make sure its a valid channel number */ if ((j < 1) || (j >= maxchans)) return -EINVAL; /* if channel not mapped, not there */ if (!chans[j]) return -EINVAL; + mychan = kmalloc(sizeof(struct zt_chan), GFP_KERNEL); + printk("CHANDIAG: Zaptel Channel %d mychan:%p from:%p size:%d\n", + j, mychan, chans[j], sizeof(struct zt_chan)); + if(!mychan) return -EINVAL; /* lock irq state */ spin_lock_irqsave(&chans[j]->lock, flags); /* make static copy of channel */ - memcpy(&mychan,chans[j],sizeof(struct zt_chan)); + memcpy(mychan,chans[j],sizeof(struct zt_chan)); /* let irq's go */ spin_unlock_irqrestore(&chans[j]->lock, flags); - printk("Dump of Zaptel Channel %d (%s,%d,%d):\n\n",j, - mychan.name,mychan.channo,mychan.chanpos); - printk("flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", - mychan.flags, (long) mychan.writechunk, (long) mychan.readchunk); - printk("rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", - (long) mychan.rxgain, (long)mychan.txgain, mychan.gainalloc); - printk("span: %08lx, sig: %x hex, sigcap: %x hex\n", - (long)mychan.span, mychan.sig, mychan.sigcap); - printk("inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", - mychan.inreadbuf, mychan.outreadbuf, mychan.inwritebuf, mychan.outwritebuf); - printk("blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", - mychan.blocksize, mychan.numbufs, mychan.txbufpolicy, mychan.rxbufpolicy); - printk("txdisable: %d, rxdisable: %d, iomask: %d\n", - mychan.txdisable, mychan.rxdisable, mychan.iomask); - printk("curzone: %08lx, tonezone: %d, curtone: %08lx, tonep: %d\n", - (long) mychan.curzone, mychan.tonezone, (long) mychan.curtone, mychan.tonep); - printk("digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", - mychan.digitmode, mychan.txdialbuf, mychan.dialing, - mychan.afterdialingtimer, mychan.cadencepos); - printk("confna: %d, confn: %d, confmode: %d, confmute: %d\n", - mychan.confna, mychan._confn, mychan.confmode, mychan.confmute); - printk("ec: %08lx, echocancel: %d, deflaw: %d, xlaw: %08lx\n", - (long) mychan.ec, mychan.echocancel, mychan.deflaw, (long) mychan.xlaw); - printk("echostate: %02x, echotimer: %d, echolastupdate: %d\n", - (int) mychan.echostate, mychan.echotimer, mychan.echolastupdate); - printk("itimer: %d, otimer: %d, ringdebtimer: %d\n\n", - mychan.itimer,mychan.otimer,mychan.ringdebtimer); + printk("CHANDIAG: Dump of Zaptel Channel %d (%s,%d,%d):\n",j, + mychan->name,mychan->channo,mychan->chanpos); + printk("CHANDIAG: flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", + mychan->flags, (long) mychan->writechunk, (long) mychan->readchunk); + printk("CHANDIAG: rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", + (long) mychan->rxgain, (long)mychan->txgain, mychan->gainalloc); + printk("CHANDIAG: span: %08lx, sig: %x hex, sigcap: %x hex\n", + (long)mychan->span, mychan->sig, mychan->sigcap); + printk("CHANDIAG: inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", + mychan->inreadbuf, mychan->outreadbuf, mychan->inwritebuf, mychan->outwritebuf); + printk("CHANDIAG: blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", + mychan->blocksize, mychan->numbufs, mychan->txbufpolicy, mychan->rxbufpolicy); + printk("CHANDIAG: txdisable: %d, rxdisable: %d, iomask: %d\n", + mychan->txdisable, mychan->rxdisable, mychan->iomask); + printk("CHANDIAG: curzone: %08lx, tonezone: %d, curtone: %08lx, tonep: %d\n", + (long) mychan->curzone, mychan->tonezone, (long) mychan->curtone, mychan->tonep); + printk("CHANDIAG: digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", + mychan->digitmode, mychan->txdialbuf, mychan->dialing, + mychan->afterdialingtimer, mychan->cadencepos); + printk("CHANDIAG: confna: %d, confn: %d, confmode: %d, confmute: %d\n", + mychan->confna, mychan->_confn, mychan->confmode, mychan->confmute); + printk("CHANDIAG: ec: %08lx, echocancel: %d, deflaw: %d, xlaw: %08lx\n", + (long) mychan->ec, mychan->echocancel, mychan->deflaw, (long) mychan->xlaw); + printk("CHANDIAG: echostate: %02x, echotimer: %d, echolastupdate: %d\n", + (int) mychan->echostate, mychan->echotimer, mychan->echolastupdate); + printk("CHANDIAG: itimer: %d, otimer: %d, ringdebtimer: %d\n\n", + mychan->itimer,mychan->otimer,mychan->ringdebtimer); #if 0 - if (mychan.ec) { + if (mychan->ec) { int x; /* Dump the echo canceller parameters */ - for (x=0;xtaps;x++) { - printk("tap %d: %d\n", x, mychan.ec->fir_taps[x]); + for (x=0;xec->taps;x++) { + printk("CHANDIAG: tap %d: %d\n", x, mychan->ec->fir_taps[x]); } } #endif -#endif /* ALLOW_CHAN_DIAG */ + kfree(mychan); + } break; default: return -ENOTTY;