summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-04-04 16:25:23 +0000
committerShaun Ruffell <sruffell@digium.com>2011-04-04 16:25:23 +0000
commit9331138caf0c62c6efb433719ea0e85ea419cdfa (patch)
tree2305fafaa852e7500ea330fab9e52e23cdc13055
parentc1762406d8b62ab79a1900469fea0ed6c05f6394 (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.c57
-rw-r--r--include/dahdi/kernel.h45
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;