diff options
author | Shaun Ruffell <sruffell@digium.com> | 2011-04-04 16:25:23 +0000 |
---|---|---|
committer | Shaun Ruffell <sruffell@digium.com> | 2011-04-04 16:25:23 +0000 |
commit | 9331138caf0c62c6efb433719ea0e85ea419cdfa (patch) | |
tree | 2305fafaa852e7500ea330fab9e52e23cdc13055 | |
parent | c1762406d8b62ab79a1900469fea0ed6c05f6394 (diff) |
dahdi: Add in-hardirq versions of the dahdi_receive/transmit/ec_span.
Since cli/sti are expensive instructions, if the board drivers are
calling receive/transmit/ec_span from interrupt context all local
interrupts do not need to be disabled. The board drivers all still use
the normal dahdi_receive and dahdi_transmit. _dahdi_receive and
_dahdi_transmit are the "in-hardirq" versions of those functions.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Michael Spiceland <mspiceland@digium.com>
Acked-by: Kinsey Moore <kmoore@digium.com>
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9884 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r-- | drivers/dahdi/dahdi-base.c | 57 | ||||
-rw-r--r-- | include/dahdi/kernel.h | 45 |
2 files changed, 65 insertions, 37 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 412101e..2de2874 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -119,16 +119,12 @@ EXPORT_SYMBOL(__dahdi_lineartoalaw); EXPORT_SYMBOL(__dahdi_lin2mu); EXPORT_SYMBOL(__dahdi_lin2a); #endif -EXPORT_SYMBOL(dahdi_transmit); -EXPORT_SYMBOL(dahdi_receive); EXPORT_SYMBOL(dahdi_rbsbits); EXPORT_SYMBOL(dahdi_qevent_nolock); EXPORT_SYMBOL(dahdi_qevent_lock); EXPORT_SYMBOL(dahdi_hooksig); EXPORT_SYMBOL(dahdi_alarm_notify); EXPORT_SYMBOL(dahdi_set_dynamic_ioctl); -EXPORT_SYMBOL(dahdi_ec_chunk); -EXPORT_SYMBOL(dahdi_ec_span); EXPORT_SYMBOL(dahdi_hdlc_abort); EXPORT_SYMBOL(dahdi_hdlc_finish); EXPORT_SYMBOL(dahdi_hdlc_getbuf); @@ -7635,7 +7631,8 @@ static void process_echocan_events(struct dahdi_chan *chan) } } -static inline void __dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) +static void +__dahdi_ec_chunk(struct dahdi_chan *ss, u8 *rxchunk, const u8 *txchunk) { short rxlin, txlin; int x; @@ -7704,7 +7701,7 @@ static inline void __dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchun } /** - * dahdi_ec_chunk() - process echo for a single channel + * _dahdi_ec_chunk() - process echo for a single channel * @ss: DAHDI channel * @rxchunk: chunk of audio on which to cancel echo * @txchunk: reference chunk from the other direction @@ -7713,14 +7710,16 @@ static inline void __dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchun * audio. In order to fix it it uses the transmitted audio as a * reference. This call updates the echo canceller for a single chunk (8 * bytes). + * + * Call with local interrupts disabled. */ -void dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) +void _dahdi_ec_chunk(struct dahdi_chan *ss, u8 *rxchunk, const u8 *txchunk) { - unsigned long flags; - spin_lock_irqsave(&ss->lock, flags); + spin_lock(&ss->lock); __dahdi_ec_chunk(ss, rxchunk, txchunk); - spin_unlock_irqrestore(&ss->lock, flags); + spin_unlock(&ss->lock); } +EXPORT_SYMBOL(_dahdi_ec_chunk); /** * dahdi_ec_span() - process echo for all channels in a span. @@ -7730,11 +7729,9 @@ void dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchunk, const unsigne * span. Uses dahdi_chunk.write_chunk for the rxchunk (the chunk to fix) * and dahdi_chan.readchunk as the txchunk (the reference chunk). */ -void dahdi_ec_span(struct dahdi_span *span) +void _dahdi_ec_span(struct dahdi_span *span) { int x; - unsigned long flags; - local_irq_save(flags); for (x = 0; x < span->channels; x++) { if (span->chans[x]->ec_current) { spin_lock(&span->chans[x]->lock); @@ -7742,8 +7739,8 @@ void dahdi_ec_span(struct dahdi_span *span) spin_unlock(&span->chans[x]->lock); } } - local_irq_restore(flags); } +EXPORT_SYMBOL(_dahdi_ec_span); /* return 0 if nothing detected, 1 if lack of tone, 2 if presence of tone */ /* modifies buffer pointed to by 'amp' with notched-out values */ @@ -8710,13 +8707,10 @@ static void __transmit_to_slaves(struct dahdi_chan *const chan) } } -int dahdi_transmit(struct dahdi_span *span) +int _dahdi_transmit(struct dahdi_span *span) { - unsigned long flags; unsigned int x; - local_irq_save(flags); - for (x=0;x<span->channels;x++) { struct dahdi_chan *const chan = span->chans[x]; spin_lock(&chan->lock); @@ -8756,8 +8750,6 @@ int dahdi_transmit(struct dahdi_span *span) spin_unlock(&chan->lock); } - local_irq_restore(flags); - if (span->mainttimer) { span->mainttimer -= DAHDI_CHUNKSIZE; if (span->mainttimer <= 0) { @@ -8767,6 +8759,7 @@ int dahdi_transmit(struct dahdi_span *span) } return 0; } +EXPORT_SYMBOL(_dahdi_transmit); static inline void __pseudo_rx_audio(struct dahdi_chan *chan) { @@ -8801,7 +8794,7 @@ static inline void dahdi_sync_tick(struct dahdi_span *const s) #endif /** - * process_masterspan - Handle conferencing and timers. + * _process_masterspan - Handle conferencing and timers. * * There are three sets of conference sum accumulators. One for the current * sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and @@ -8837,9 +8830,8 @@ static inline void dahdi_sync_tick(struct dahdi_span *const s) * of the next sample chunk's data (next time around the world). * */ -static void process_masterspan(void) +static void _process_masterspan(void) { - unsigned long flags; int x; struct pseudo_chan *pseudo; struct dahdi_span *s; @@ -8854,7 +8846,7 @@ static void process_masterspan(void) #endif /* Hold the chan_lock for the duration of major activities which touch all sorts of channels */ - spin_lock_irqsave(&chan_lock, flags); + spin_lock(&chan_lock); /* Process any timers */ process_timers(); @@ -8903,7 +8895,7 @@ static void process_masterspan(void) dahdi_sync_tick(s); } - spin_unlock_irqrestore(&chan_lock, flags); + spin_unlock(&chan_lock); } #ifndef CONFIG_DAHDI_CORE_TIMER @@ -8945,6 +8937,7 @@ static inline unsigned long msecs_processed(const struct core_timer *const ct) static void coretimer_func(unsigned long param) { + unsigned long flags; unsigned long ms_since_start; struct timespec now; const unsigned long MAX_INTERVAL = 100000L; @@ -8987,8 +8980,10 @@ static void coretimer_func(unsigned long param) return; } + local_irq_save(flags); while (ms_since_start > msecs_processed(&core_timer)) - process_masterspan(); + _process_masterspan(); + local_irq_restore(flags); if (ms_since_start > MAX_INTERVAL) { atomic_set(&core_timer.count, 0); @@ -9062,16 +9057,13 @@ static inline bool should_skip_receive(const struct dahdi_chan *const chan) is_chan_dacsed(chan)); } -int dahdi_receive(struct dahdi_span *span) +int _dahdi_receive(struct dahdi_span *span) { - unsigned long flags; unsigned int x; #ifdef CONFIG_DAHDI_WATCHDOG span->watchcounter--; #endif - local_irq_save(flags); - for (x = 0; x < span->channels; x++) { struct dahdi_chan *const chan = span->chans[x]; spin_lock(&chan->lock); @@ -9132,13 +9124,12 @@ int dahdi_receive(struct dahdi_span *span) spin_unlock(&chan->lock); } - local_irq_restore(flags); - if (span == master) - process_masterspan(); + _process_masterspan(); return 0; } +EXPORT_SYMBOL(_dahdi_receive); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); MODULE_DESCRIPTION("DAHDI Telephony Interface"); diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h index c289429..5b04918 100644 --- a/include/dahdi/kernel.h +++ b/include/dahdi/kernel.h @@ -1048,12 +1048,32 @@ int dahdi_dynamic_register_driver(struct dahdi_dynamic_driver *driver); /*! \brief Unregister a dynamic driver */ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *driver); +int _dahdi_receive(struct dahdi_span *span); + /*! Receive on a span. The DAHDI interface will handle all the calculations for all member channels of the span, pulling the data from the readchunk buffer */ -int dahdi_receive(struct dahdi_span *span); +static inline int dahdi_receive(struct dahdi_span *span) +{ + unsigned long flags; + int ret; + local_irq_save(flags); + ret = _dahdi_receive(span); + local_irq_restore(flags); + return ret; +} + +int _dahdi_transmit(struct dahdi_span *span); /*! Prepare writechunk buffers on all channels for this span */ -int dahdi_transmit(struct dahdi_span *span); +static inline int dahdi_transmit(struct dahdi_span *span) +{ + unsigned long flags; + int ret; + local_irq_save(flags); + ret = _dahdi_transmit(span); + local_irq_restore(flags); + return ret; +} /*! Abort the buffer currently being receive with event "event" */ void dahdi_hdlc_abort(struct dahdi_chan *ss, int event); @@ -1122,9 +1142,26 @@ struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE AT THE DAHDI LEVEL. dahdi_ec_chunk will not echo cancel if it should not be doing so. rxchunk is modified in-place */ +void _dahdi_ec_chunk(struct dahdi_chan *chan, unsigned char *rxchunk, + const unsigned char *txchunk); -void dahdi_ec_chunk(struct dahdi_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); -void dahdi_ec_span(struct dahdi_span *span); +static inline void dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchunk, + const unsigned char *txchunk) +{ + unsigned long flags; + local_irq_save(flags); + _dahdi_ec_chunk(ss, rxchunk, txchunk); + local_irq_restore(flags); +} + +void _dahdi_ec_span(struct dahdi_span *span); +static inline void dahdi_ec_span(struct dahdi_span *span) +{ + unsigned long flags; + local_irq_save(flags); + _dahdi_ec_span(span); + local_irq_restore(flags); +} extern struct file_operations *dahdi_transcode_fops; |