diff options
author | russell <russell@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-03 23:39:58 +0000 |
---|---|---|
committer | russell <russell@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-03 23:39:58 +0000 |
commit | 8a937ac5a4588ffa815a2b20e94b3a96e13651b5 (patch) | |
tree | f1074f92f5908397d9b20e1955938277f346ebf2 | |
parent | 4556d32068aaaa651c25a7705c3a9c8bcdafa5f1 (diff) |
The ZT_CHANDIAG ioctl was disabled by default because the large zt_chan struct
that was being allocated on the stack is too big for some systems (those with
4k stacks). So, change the code to allocate the struct on the heap, and let
the ioctl be always enabled. (issue #9364, patch by tzafrir, with minor mods)
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@2384 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r-- | zaptel.c | 55 |
1 files changed, 29 insertions, 26 deletions
@@ -2943,10 +2943,8 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c 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 + struct zt_chan *mychan; int i,j; int return_master = 0; @@ -3156,57 +3154,62 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c if (copy_to_user((struct zt_spaninfo *) data,&stack.span,sizeof(stack.span))) return -EFAULT; break; -#ifdef ALLOW_CHAN_DIAG case ZT_CHANDIAG: 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; - /* lock irq state */ + if (!chans[j]) + return -EINVAL; + + if (!(mychan = kmalloc(sizeof(*mychan), GFP_KERNEL))) + return -ENOMEM; + + /* lock channel */ spin_lock_irqsave(&chans[j]->lock, flags); /* make static copy of channel */ - memcpy(&mychan,chans[j],sizeof(struct zt_chan)); - /* let irq's go */ + memcpy(mychan, chans[j], sizeof(*mychan)); + /* release it. */ 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); + mychan->name,mychan->channo,mychan->chanpos); printk("flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", - mychan.flags, (long) mychan.writechunk, (long) mychan.readchunk); + mychan->flags, (long) mychan->writechunk, (long) mychan->readchunk); printk("rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", - (long) mychan.rxgain, (long)mychan.txgain, mychan.gainalloc); + (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); + (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); + 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); + mychan->blocksize, mychan->numbufs, mychan->txbufpolicy, mychan->rxbufpolicy); printk("txdisable: %d, rxdisable: %d, iomask: %d\n", - mychan.txdisable, mychan.rxdisable, mychan.iomask); + 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); + (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); + 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); + 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); + (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); + (int) mychan->echostate, mychan->echotimer, mychan->echolastupdate); printk("itimer: %d, otimer: %d, ringdebtimer: %d\n\n", - mychan.itimer,mychan.otimer,mychan.ringdebtimer); + mychan->itimer, mychan->otimer, mychan->ringdebtimer); #if 0 - if (mychan.ec) { + if (mychan->ec) { int x; /* Dump the echo canceller parameters */ - for (x=0;x<mychan.ec->taps;x++) { - printk("tap %d: %d\n", x, mychan.ec->fir_taps[x]); + for (x=0;x<mychan->ec->taps;x++) { + printk("tap %d: %d\n", x, mychan->ec->fir_taps[x]); } } #endif -#endif /* ALLOW_CHAN_DIAG */ + kfree(mychan); break; default: return -ENOTTY; |