diff options
author | Kevin P. Fleming <kpfleming@digium.com> | 2008-07-02 13:31:31 +0000 |
---|---|---|
committer | Kevin P. Fleming <kpfleming@digium.com> | 2008-07-02 13:31:31 +0000 |
commit | 1340abc2e710509a9bbe8ca720c91eff896c3d33 (patch) | |
tree | 3d2cffb2090c445da8b3b8e741543c0287a2cc60 /drivers/dahdi/wct1xxp.c | |
parent | ef05eedbe6bffbdaaee55f26b0c54a06fd32b6f2 (diff) |
break up large memory allocations made by digital span drivers into smaller ones (one allocation for each dahdi_chan structure, separate from any private structures used by the driver)
(closes issue #12657)
Reported by: tzafrir
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@4513 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/wct1xxp.c')
-rw-r--r-- | drivers/dahdi/wct1xxp.c | 182 |
1 files changed, 100 insertions, 82 deletions
diff --git a/drivers/dahdi/wct1xxp.c b/drivers/dahdi/wct1xxp.c index 54377bf..c59cf1a 100644 --- a/drivers/dahdi/wct1xxp.c +++ b/drivers/dahdi/wct1xxp.c @@ -161,7 +161,7 @@ struct t1xxp { unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE]; unsigned char tempo[32]; struct dahdi_span span; /* Span */ - struct dahdi_chan chans[31]; /* Channels */ + struct dahdi_chan *chans[31]; /* Channels */ }; #define CANARY 0xca1e @@ -272,7 +272,12 @@ static int control_get_reg(struct t1xxp *wc, int reg) static void t1xxp_release(struct t1xxp *wc) { + unsigned int x; + dahdi_unregister(&wc->span); + for (x = 0; x < (wc->ise1 ? 31 : 24); x++) { + kfree(wc->chans[x]); + } kfree(wc); printk("Freed a Wildcard\n"); } @@ -334,7 +339,7 @@ static void __t1xxp_set_clear(struct t1xxp *wc) for (x=0;x<3;x++) { b = 0; for (y=0;y<8;y++) - if (wc->chans[x * 8 + y].sig & DAHDI_SIG_CLEAR) + if (wc->chans[x * 8 + y]->sig & DAHDI_SIG_CLEAR) b |= (1 << y); __t1_set_reg(wc, 0x39 + x, b); } @@ -555,14 +560,14 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits) spin_lock_irqsave(&wc->lock, flags); if (wc->ise1) { if (chan->chanpos < 16) { - mask = ((bits << 4) | wc->chans[chan->chanpos - 1 + 16].txsig); + mask = ((bits << 4) | wc->chans[chan->chanpos - 1 + 16]->txsig); __t1_set_reg(wc, 0x40 + chan->chanpos, mask); } else if (chan->chanpos > 16) { - mask = (bits | (wc->chans[chan->chanpos - 1 - 16].txsig << 4)); + mask = (bits | (wc->chans[chan->chanpos - 1 - 16]->txsig << 4)); __t1_set_reg(wc, 0x40 + chan->chanpos - 16, mask); } - wc->chans[chan->chanpos - 1].txsig = bits; + wc->chans[chan->chanpos - 1]->txsig = bits; } else { b = (chan->chanpos - 1) / 8; o = (chan->chanpos - 1) % 8; @@ -610,9 +615,9 @@ static int t1xxp_startup(struct dahdi_span *span) for(i = 0; i < span->channels; i++) { memset(wc->ec_chunk1[i], - DAHDI_LIN2X(0,&span->chans[i]),DAHDI_CHUNKSIZE); + DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE); memset(wc->ec_chunk2[i], - DAHDI_LIN2X(0,&span->chans[i]),DAHDI_CHUNKSIZE); + DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE); } /* Reset framer with proper parameters and start */ @@ -781,13 +786,13 @@ static int t1xxp_software_init(struct t1xxp *wc) } init_waitqueue_head(&wc->span.maintq); for (x=0;x<wc->span.channels;x++) { - sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); - wc->chans[x].sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_EM_E1 | + sprintf(wc->chans[x]->name, "WCT1/%d/%d", wc->num, x + 1); + wc->chans[x]->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_EM_E1 | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_DACS_RBS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF; - wc->chans[x].pvt = wc; - wc->chans[x].chanpos = x + 1; + wc->chans[x]->pvt = wc; + wc->chans[x]->chanpos = x + 1; } if (dahdi_register(&wc->span, 0)) { printk("Unable to register span with DAHDI\n"); @@ -870,9 +875,9 @@ static void t1xxp_transmitprep(struct t1xxp *wc, int ints) pos = y * 32 + wc->chanmap[x] + wc->offset; /* Put channel number as outgoing data */ if (pos < 32 * DAHDI_CHUNKSIZE) - txbuf[pos] = wc->chans[x].writechunk[y]; + txbuf[pos] = wc->chans[x]->writechunk[y]; else - wc->tempo[pos - 32 * DAHDI_CHUNKSIZE] = wc->chans[x].writechunk[y]; + wc->tempo[pos - 32 * DAHDI_CHUNKSIZE] = wc->chans[x]->writechunk[y]; } } } @@ -905,7 +910,7 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints) for (x=0;x<wc->span.channels;x++) { /* XXX Optimize, remove * and + XXX */ /* Must map received channels into appropriate data */ - wc->chans[x].readchunk[y] = + wc->chans[x]->readchunk[y] = rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; } if (!wc->ise1) { @@ -944,10 +949,9 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints) canary = (unsigned int *)(rxbuf + DAHDI_CHUNKSIZE * 32 - 4); *canary = (wc->canary++) | (CANARY << 16); for (x=0;x<wc->span.channels;x++) { - dahdi_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, - wc->ec_chunk2[x]); + dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->ec_chunk2[x]); memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],DAHDI_CHUNKSIZE); - memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,DAHDI_CHUNKSIZE); + memcpy(wc->ec_chunk1[x],wc->chans[x]->writechunk,DAHDI_CHUNKSIZE); } dahdi_receive(&wc->span); } @@ -964,18 +968,18 @@ static void t1xxp_check_sigbits(struct t1xxp *wc, int x) a = __t1_get_reg(wc, 0x31 + i); /* Get high channel in low bits */ rxs = (a & 0xf); - if (!(wc->chans[i+16].sig & DAHDI_SIG_CLEAR)) { - if (wc->chans[i+16].rxsig != rxs) { + if (!(wc->chans[i+16]->sig & DAHDI_SIG_CLEAR)) { + if (wc->chans[i+16]->rxsig != rxs) { spin_unlock_irqrestore(&wc->lock, flags); - dahdi_rbsbits(&wc->chans[i+16], rxs); + dahdi_rbsbits(wc->chans[i+16], rxs); spin_lock_irqsave(&wc->lock, flags); } } rxs = (a >> 4) & 0xf; - if (!(wc->chans[i].sig & DAHDI_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) { + if (!(wc->chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (wc->chans[i]->rxsig != rxs) { spin_unlock_irqrestore(&wc->lock, flags); - dahdi_rbsbits(&wc->chans[i], rxs); + dahdi_rbsbits(wc->chans[i], rxs); spin_lock_irqsave(&wc->lock, flags); } } @@ -990,10 +994,10 @@ static void t1xxp_check_sigbits(struct t1xxp *wc, int x) rxs |= DAHDI_ABIT; if (b & (1 << y)) rxs |= DAHDI_BBIT; - if (!(wc->chans[i].sig & DAHDI_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) { + if (!(wc->chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (wc->chans[i]->rxsig != rxs) { spin_unlock_irqrestore(&wc->lock, flags); - dahdi_rbsbits(&wc->chans[i], rxs); + dahdi_rbsbits(wc->chans[i], rxs); spin_lock_irqsave(&wc->lock, flags); } } @@ -1058,8 +1062,8 @@ static void t1xxp_check_alarms(struct t1xxp *wc) if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { for (x=0,j=0;x < wc->span.channels;x++) - if ((wc->chans[x].flags & DAHDI_FLAG_OPEN) || - (wc->chans[x].flags & DAHDI_FLAG_NETDEV)) + if ((wc->chans[x]->flags & DAHDI_FLAG_OPEN) || + (wc->chans[x]->flags & DAHDI_FLAG_NETDEV)) j++; if (!j) alarms |= DAHDI_ALARM_NOTOPEN; @@ -1266,72 +1270,86 @@ static int t1xxp_hardware_init(struct t1xxp *wc) static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int res; struct t1xxp *wc; unsigned int *canary; + unsigned int x; - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - wc = kmalloc(sizeof(struct t1xxp), GFP_KERNEL); - if (wc) { - memset(wc, 0x0, sizeof(struct t1xxp)); - spin_lock_init(&wc->lock); - wc->ioaddr = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->offset = 28; /* And you thought 42 was the answer */ - - wc->writechunk = - /* 32 channels, Double-buffer, Read/Write */ - (unsigned char *)pci_alloc_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); - if (!wc->writechunk) { - printk("wct1xxp: Unable to allocate DMA-able memory\n"); - return -ENOMEM; - } - - /* Read is after the whole write piece (in bytes) */ - wc->readchunk = wc->writechunk + DAHDI_CHUNKSIZE * 32 * 2; - - /* Same thing... */ - wc->readdma = wc->writedma + DAHDI_CHUNKSIZE * 32 * 2; - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0x00,DAHDI_MAX_CHUNKSIZE * 2 * 2 * 32); - /* Initialize canary */ - canary = (unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 64 - 4); - *canary = (CANARY << 16) | (0xffff); + if (!pci_enable_device(pdev)) { + return -EIO; + } - /* Enable bus mastering */ - pci_set_master(pdev); + if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) { + return -ENOMEM; + } - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); + memset(wc, 0x0, sizeof(*wc)); + spin_lock_init(&wc->lock); + wc->ioaddr = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->offset = 28; /* And you thought 42 was the answer */ + + wc->writechunk = + /* 32 channels, Double-buffer, Read/Write */ + (unsigned char *)pci_alloc_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); + if (!wc->writechunk) { + printk("wct1xxp: Unable to allocate DMA-able memory\n"); + return -ENOMEM; + } + + /* Read is after the whole write piece (in bytes) */ + wc->readchunk = wc->writechunk + DAHDI_CHUNKSIZE * 32 * 2; + + /* Same thing... */ + wc->readdma = wc->writedma + DAHDI_CHUNKSIZE * 32 * 2; + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00,DAHDI_MAX_CHUNKSIZE * 2 * 2 * 32); + /* Initialize canary */ + canary = (unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 64 - 4); + *canary = (CANARY << 16) | (0xffff); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, t1xxp_interrupt, DAHDI_IRQ_SHARED_DISABLED, "t1xxp", wc)) { + printk("t1xxp: Unable to request IRQ %d\n", pdev->irq); + kfree(wc); + return -EIO; + } + /* Initialize hardware */ + t1xxp_hardware_init(wc); + + /* We now know which version of card we have */ + if (wc->ise1) { + wc->variety = "Digium Wildcard E100P E1/PRA"; + } else { + wc->variety = "Digium Wildcard T100P T1/PRI"; + } - if (request_irq(pdev->irq, t1xxp_interrupt, DAHDI_IRQ_SHARED_DISABLED, "t1xxp", wc)) { - printk("t1xxp: Unable to request IRQ %d\n", pdev->irq); - kfree(wc); - return -EIO; + for (x = 0; x < (wc->ise1 ? 31 : 24); x++) { + if (!(wc->chans[x] = kmalloc(sizeof(*wc->chans[x]), GFP_KERNEL))) { + while (x) { + kfree(wc->chans[--x]); } - /* Initialize hardware */ - t1xxp_hardware_init(wc); - /* We now know which version of card we have */ - if (wc->ise1) - wc->variety = "Digium Wildcard E100P E1/PRA"; - else - wc->variety = "Digium Wildcard T100P T1/PRI"; + kfree(wc); + return -ENOMEM; + } + memset(wc->chans[x], 0, sizeof(*wc->chans[x])); + } - /* Misc. software stuff */ - t1xxp_software_init(wc); + /* Misc. software stuff */ + t1xxp_software_init(wc); + + printk("Found a Wildcard: %s\n", wc->variety); - printk("Found a Wildcard: %s\n", wc->variety); - res = 0; - } else - res = -ENOMEM; - } - return res; + return 0; } + static void t1xxp_stop_stuff(struct t1xxp *wc) { /* Kill clock */ |