summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrussell <russell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-03 23:39:58 +0000
committerrussell <russell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-03 23:39:58 +0000
commit8a937ac5a4588ffa815a2b20e94b3a96e13651b5 (patch)
treef1074f92f5908397d9b20e1955938277f346ebf2
parent4556d32068aaaa651c25a7705c3a9c8bcdafa5f1 (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.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/zaptel.c b/zaptel.c
index 5f01539..3d27b28 100644
--- a/zaptel.c
+++ b/zaptel.c
@@ -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;