From 1340abc2e710509a9bbe8ca720c91eff896c3d33 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Wed, 2 Jul 2008 13:31:31 +0000 Subject: 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 --- drivers/dahdi/wcte12xp/base.c | 102 ++++++++++++++++++++++--------------- drivers/dahdi/wcte12xp/vpmadt032.c | 2 +- drivers/dahdi/wcte12xp/wcte12xp.h | 2 +- 3 files changed, 62 insertions(+), 44 deletions(-) (limited to 'drivers/dahdi/wcte12xp') diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index 422b704..3b284f5 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -437,7 +437,7 @@ static void __t1xxp_set_clear(struct t1 *wc, int channo) for (i = 0; i < 24; i++) { j = (i / 8); - if (wc->span.chans[i].flags & DAHDI_FLAG_CLEAR) + if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR) val |= 1 << (7 - (i % 8)); if (((i % 8)==7) && /* write byte every 8 channels */ ((channo < 0) || /* channo=-1 means all channels */ @@ -452,7 +452,12 @@ static void __t1xxp_set_clear(struct t1 *wc, int channo) static void t1_release(struct t1 *wc) { + unsigned int x; + dahdi_unregister(&wc->span); + for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) { + kfree(wc->chans[x]); + } kfree(wc); printk("Freed a Wildcard TE12xP\n"); } @@ -688,8 +693,8 @@ static int t1xxp_startup(struct dahdi_span *span) /* initialize the start value for the entire chunk of last ec buffer */ for (i = 0; i < span->channels; i++) { - memset(wc->ec_chunk1[i], DAHDI_LIN2X(0, &span->chans[i]), DAHDI_CHUNKSIZE); - memset(wc->ec_chunk2[i], DAHDI_LIN2X(0, &span->chans[i]), DAHDI_CHUNKSIZE); + memset(wc->ec_chunk1[i], DAHDI_LIN2X(0, span->chans[i]), DAHDI_CHUNKSIZE); + memset(wc->ec_chunk2[i], DAHDI_LIN2X(0, span->chans[i]), DAHDI_CHUNKSIZE); } /* Reset framer with proper parameters and start */ @@ -831,18 +836,18 @@ static inline void __t1_check_sigbits(struct t1 *wc) if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); - if (!(wc->span.chans[i+16].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i+16].rxsig != rxs) { + if (!(wc->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i+16]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i+16], rxs); + dahdi_rbsbits(wc->span.chans[i+16], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 4) & 0xf; - if (!(wc->span.chans[i].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { + if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i], rxs); + dahdi_rbsbits(wc->span.chans[i], rxs); spin_lock(&wc->reglock); } } @@ -854,34 +859,34 @@ static inline void __t1_check_sigbits(struct t1 *wc) if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0x3) << 2; - if (!(wc->span.chans[i+3].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i+3].rxsig != rxs) { + if (!(wc->span.chans[i+3]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i+3]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i+3], rxs); + dahdi_rbsbits(wc->span.chans[i+3], rxs); spin_lock(&wc->reglock); } } rxs = (a & 0xc); - if (!(wc->span.chans[i+2].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i+2].rxsig != rxs) { + if (!(wc->span.chans[i+2]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i+2]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i+2], rxs); + dahdi_rbsbits(wc->span.chans[i+2], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 2) & 0xc; - if (!(wc->span.chans[i+1].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) { + if (!(wc->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i+1]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i+1], rxs); + dahdi_rbsbits(wc->span.chans[i+1], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 4) & 0xc; - if (!(wc->span.chans[i].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { + if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i], rxs); + dahdi_rbsbits(wc->span.chans[i], rxs); spin_lock(&wc->reglock); } } @@ -893,18 +898,18 @@ static inline void __t1_check_sigbits(struct t1 *wc) if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); - if (!(wc->span.chans[i+1].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) { + if (!(wc->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i+1]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i+1], rxs); + dahdi_rbsbits(wc->span.chans[i+1], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 4) & 0xf; - if (!(wc->span.chans[i].sig & DAHDI_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { + if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (wc->span.chans[i]->rxsig != rxs) { spin_unlock(&wc->reglock); - dahdi_rbsbits(&wc->span.chans[i], rxs); + dahdi_rbsbits(wc->span.chans[i], rxs); spin_lock(&wc->reglock); } } @@ -1152,13 +1157,13 @@ static int t1_software_init(struct t1 *wc) wc->span.pvt = 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_MTP2 | 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)) { module_printk("Unable to register span with DAHDI\n"); @@ -1318,8 +1323,8 @@ static inline void __t1_check_alarms(struct t1 *wc) if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { for (x=0,j=0;x < wc->span.channels;x++) - if ((wc->span.chans[x].flags & DAHDI_FLAG_OPEN) || - (wc->span.chans[x].flags & DAHDI_FLAG_NETDEV)) + if ((wc->span.chans[x]->flags & DAHDI_FLAG_OPEN) || + (wc->span.chans[x]->flags & DAHDI_FLAG_NETDEV)) j++; if (!j) alarms |= DAHDI_ALARM_NOTOPEN; @@ -1460,7 +1465,7 @@ static inline void t1_transmitprep(struct t1 *wc, unsigned char* writechunk) for (x = 0; x < DAHDI_CHUNKSIZE; x++) { if (likely(wc->initialized)) { for (chan = 0; chan < wc->span.channels; chan++) - writechunk[(chan+1)*2] = wc->chans[chan].writechunk[x]; + writechunk[(chan+1)*2] = wc->chans[chan]->writechunk[x]; } /* process the command queue */ @@ -1501,7 +1506,7 @@ static inline void t1_receiveprep(struct t1 *wc, unsigned char* readchunk) for (x = 0; x < DAHDI_CHUNKSIZE; x++) { if (likely(wc->initialized)) { for (chan = 0; chan < wc->span.channels; chan++) { - wc->chans[chan].readchunk[x]= readchunk[(chan+1)*2]; + wc->chans[chan]->readchunk[x]= readchunk[(chan+1)*2]; } } if (x < DAHDI_CHUNKSIZE - 1) { @@ -1527,9 +1532,9 @@ static inline void t1_receiveprep(struct t1 *wc, unsigned char* readchunk) if (likely(wc->initialized)) { spin_unlock(&wc->reglock); 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); spin_lock(&wc->reglock); @@ -1588,9 +1593,9 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi } retry: - wc = kmalloc(sizeof(*wc), GFP_KERNEL); - if (!wc) + if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) { return -ENOMEM; + } ifaces[x] = wc; memset(wc, 0, sizeof(*wc)); @@ -1600,9 +1605,8 @@ retry: init_waitqueue_head(&wc->regq); snprintf(wc->name, sizeof(wc->name)-1, "wcte12xp%d", x); - if ((res=voicebus_init(pdev, SFRAME_SIZE, wc->name, - t1_handle_receive, t1_handle_transmit, wc, &wc->vb))) - { + if ((res = voicebus_init(pdev, SFRAME_SIZE, wc->name, + t1_handle_receive, t1_handle_transmit, wc, &wc->vb))) { WARN_ON(1); kfree(wc); return res; @@ -1616,6 +1620,19 @@ retry: voicebus_start(wc->vb); startinglatency = voicebus_current_latency(wc->vb); t1_hardware_post_init(wc); + + for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) { + if (!(wc->chans[x] = kmalloc(sizeof(*wc->chans[x]), GFP_KERNEL))) { + while (x) { + kfree(wc->chans[--x]); + } + + kfree(wc); + return -ENOMEM; + } + memset(wc->chans[x], 0, sizeof(*wc->chans[x])); + } + t1_software_init(wc); if (voicebus_current_latency(wc->vb) > startinglatency) { /* The voicebus library increased the latency during @@ -1633,6 +1650,7 @@ retry: wc = NULL; goto retry; } + module_printk("Found a %s\n", wc->variety); return 0; diff --git a/drivers/dahdi/wcte12xp/vpmadt032.c b/drivers/dahdi/wcte12xp/vpmadt032.c index f8e385b..3d02dc3 100644 --- a/drivers/dahdi/wcte12xp/vpmadt032.c +++ b/drivers/dahdi/wcte12xp/vpmadt032.c @@ -649,7 +649,7 @@ static void vpm150m_dtmf_bh(struct work_struct *data) debug_printk(1, "Channel %d: Detected DTMF tone %d of duration %d\n", channel + 1, tone, duration); if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { - struct dahdi_chan *chan = &wc->chans[channel]; + struct dahdi_chan *chan = wc->chans[channel]; module_printk("DTMF detected channel=%d tone=%d duration=%d\n", channel + 1, tone, duration); diff --git a/drivers/dahdi/wcte12xp/wcte12xp.h b/drivers/dahdi/wcte12xp/wcte12xp.h index 2ba4609..93bda0d 100644 --- a/drivers/dahdi/wcte12xp/wcte12xp.h +++ b/drivers/dahdi/wcte12xp/wcte12xp.h @@ -140,7 +140,7 @@ struct t1 { unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE]; unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE]; struct dahdi_span span; /* Span */ - struct dahdi_chan chans[32]; /* Channels */ + struct dahdi_chan *chans[32]; /* Channels */ wait_queue_head_t regq; struct cmdq cmdq; struct command dummy; /* preallocate for dummy noop command */ -- cgit v1.2.3