|
Lines 238-244
Link Here
|
| 238 |
int dst; /* dst conf number */ |
238 |
int dst; /* dst conf number */ |
| 239 |
} conf_links[DAHDI_MAX_CONF + 1]; |
239 |
} conf_links[DAHDI_MAX_CONF + 1]; |
| 240 |
|
240 |
|
|
|
241 |
#ifdef CONFIG_DAHDI_CORE_TIMER |
| 241 |
|
242 |
|
|
|
243 |
static struct core_timer { |
| 244 |
struct timer_list timer; |
| 245 |
struct timespec start_interval; |
| 246 |
atomic_t count; |
| 247 |
atomic_t shutdown; |
| 248 |
atomic_t last_count; |
| 249 |
} core_timer; |
| 250 |
|
| 251 |
#endif /* CONFIG_DAHDI_CORE_TIMER */ |
| 252 |
|
| 253 |
|
| 254 |
|
| 242 |
/* There are three sets of conference sum accumulators. One for the current |
255 |
/* There are three sets of conference sum accumulators. One for the current |
| 243 |
sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and |
256 |
sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and |
| 244 |
one for the previous sample chunk (conf_sums_prev). The following routine |
257 |
one for the previous sample chunk (conf_sums_prev). The following routine |
|
Lines 2671-2682
Link Here
|
| 2671 |
return res; |
2684 |
return res; |
| 2672 |
} |
2685 |
} |
| 2673 |
|
2686 |
|
|
|
2687 |
static int can_open_timer(void) |
| 2688 |
{ |
| 2689 |
#ifdef CONFIG_DAHDI_CORE_TIMER |
| 2690 |
return 1; |
| 2691 |
#else |
| 2692 |
return maxspans > 0; |
| 2693 |
#endif |
| 2694 |
} |
| 2695 |
|
| 2674 |
static struct dahdi_chan *dahdi_alloc_pseudo(void) |
2696 |
static struct dahdi_chan *dahdi_alloc_pseudo(void) |
| 2675 |
{ |
2697 |
{ |
| 2676 |
struct dahdi_chan *pseudo; |
2698 |
struct dahdi_chan *pseudo; |
| 2677 |
|
2699 |
|
| 2678 |
/* Don't allow /dev/dahdi/pseudo to open if there are no spans */ |
2700 |
/* Don't allow /dev/dahdi/pseudo to open if there is not a timing |
| 2679 |
if (maxspans < 1) |
2701 |
* source. */ |
|
|
2702 |
if (!can_open_timer()) |
| 2680 |
return NULL; |
2703 |
return NULL; |
| 2681 |
|
2704 |
|
| 2682 |
if (!(pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL))) |
2705 |
if (!(pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL))) |
|
Lines 2734-2740
Link Here
|
| 2734 |
return -ENXIO; |
2757 |
return -ENXIO; |
| 2735 |
} |
2758 |
} |
| 2736 |
if (unit == 253) { |
2759 |
if (unit == 253) { |
| 2737 |
if (maxspans) { |
2760 |
if (can_open_timer()) { |
| 2738 |
return dahdi_timing_open(inode, file); |
2761 |
return dahdi_timing_open(inode, file); |
| 2739 |
} else { |
2762 |
} else { |
| 2740 |
return -ENXIO; |
2763 |
return -ENXIO; |
|
Lines 2743-2758
Link Here
|
| 2743 |
if (unit == 254) |
2766 |
if (unit == 254) |
| 2744 |
return dahdi_chan_open(inode, file); |
2767 |
return dahdi_chan_open(inode, file); |
| 2745 |
if (unit == 255) { |
2768 |
if (unit == 255) { |
| 2746 |
if (maxspans) { |
2769 |
chan = dahdi_alloc_pseudo(); |
| 2747 |
chan = dahdi_alloc_pseudo(); |
2770 |
if (chan) { |
| 2748 |
if (chan) { |
2771 |
file->private_data = chan; |
| 2749 |
file->private_data = chan; |
2772 |
return dahdi_specchan_open(inode, file, chan->channo); |
| 2750 |
return dahdi_specchan_open(inode, file, chan->channo); |
2773 |
} else { |
| 2751 |
} else { |
|
|
| 2752 |
return -ENXIO; |
| 2753 |
} |
| 2754 |
} else |
| 2755 |
return -ENXIO; |
2774 |
return -ENXIO; |
|
|
2775 |
} |
| 2756 |
} |
2776 |
} |
| 2757 |
return dahdi_specchan_open(inode, file, unit); |
2777 |
return dahdi_specchan_open(inode, file, unit); |
| 2758 |
} |
2778 |
} |
|
Lines 7748-7759
Link Here
|
| 7748 |
return 0; |
7768 |
return 0; |
| 7749 |
} |
7769 |
} |
| 7750 |
|
7770 |
|
|
|
7771 |
static void process_masterspan(void) |
| 7772 |
{ |
| 7773 |
unsigned long flags; |
| 7774 |
int x, y, z; |
| 7775 |
|
| 7776 |
#ifdef CONFIG_DAHDI_CORE_TIMER |
| 7777 |
/* We increment the calls since start here, so that if we switch over |
| 7778 |
* to the core timer, we know how many times we need to call |
| 7779 |
* process_masterspan in order to catch up since this function needs |
| 7780 |
* to be called 1000 times per second. */ |
| 7781 |
atomic_inc(&core_timer.count); |
| 7782 |
#endif |
| 7783 |
/* Hold the big zap lock for the duration of major |
| 7784 |
activities which touch all sorts of channels */ |
| 7785 |
spin_lock_irqsave(&bigzaplock, flags); |
| 7786 |
read_lock(&chan_lock); |
| 7787 |
/* Process any timers */ |
| 7788 |
process_timers(); |
| 7789 |
/* If we have dynamic stuff, call the ioctl with 0,0 parameters to |
| 7790 |
make it run */ |
| 7791 |
if (dahdi_dynamic_ioctl) |
| 7792 |
dahdi_dynamic_ioctl(0, 0); |
| 7793 |
|
| 7794 |
for (x = 1; x < maxchans; x++) { |
| 7795 |
if (chans[x] && chans[x]->confmode && |
| 7796 |
!(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7797 |
u_char *data; |
| 7798 |
spin_lock(&chans[x]->lock); |
| 7799 |
data = __buf_peek(&chans[x]->confin); |
| 7800 |
__dahdi_receive_chunk(chans[x], data); |
| 7801 |
if (data) { |
| 7802 |
__buf_pull(&chans[x]->confin, NULL, chans[x], |
| 7803 |
"confreceive"); |
| 7804 |
} |
| 7805 |
spin_unlock(&chans[x]->lock); |
| 7806 |
} |
| 7807 |
} |
| 7808 |
/* This is the master channel, so make things switch over */ |
| 7809 |
rotate_sums(); |
| 7810 |
/* do all the pseudo and/or conferenced channel receives (getbuf's) */ |
| 7811 |
for (x = 1; x < maxchans; x++) { |
| 7812 |
if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7813 |
spin_lock(&chans[x]->lock); |
| 7814 |
__dahdi_transmit_chunk(chans[x], NULL); |
| 7815 |
spin_unlock(&chans[x]->lock); |
| 7816 |
} |
| 7817 |
} |
| 7818 |
if (maxlinks) { |
| 7819 |
#ifdef CONFIG_DAHDI_MMX |
| 7820 |
dahdi_kernel_fpu_begin(); |
| 7821 |
#endif |
| 7822 |
/* process all the conf links */ |
| 7823 |
for (x = 1; x <= maxlinks; x++) { |
| 7824 |
/* if we have a destination conf */ |
| 7825 |
z = confalias[conf_links[x].dst]; |
| 7826 |
if (z) { |
| 7827 |
y = confalias[conf_links[x].src]; |
| 7828 |
if (y) |
| 7829 |
ACSS(conf_sums[z], conf_sums[y]); |
| 7830 |
} |
| 7831 |
} |
| 7832 |
#ifdef CONFIG_DAHDI_MMX |
| 7833 |
dahdi_kernel_fpu_end(); |
| 7834 |
#endif |
| 7835 |
} |
| 7836 |
/* do all the pseudo/conferenced channel transmits (putbuf's) */ |
| 7837 |
for (x = 1; x < maxchans; x++) { |
| 7838 |
if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7839 |
unsigned char tmp[DAHDI_CHUNKSIZE]; |
| 7840 |
spin_lock(&chans[x]->lock); |
| 7841 |
__dahdi_getempty(chans[x], tmp); |
| 7842 |
__dahdi_receive_chunk(chans[x], tmp); |
| 7843 |
spin_unlock(&chans[x]->lock); |
| 7844 |
} |
| 7845 |
} |
| 7846 |
for (x = 1; x < maxchans; x++) { |
| 7847 |
if (chans[x] && chans[x]->confmode && |
| 7848 |
!(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7849 |
u_char *data; |
| 7850 |
spin_lock(&chans[x]->lock); |
| 7851 |
data = __buf_pushpeek(&chans[x]->confout); |
| 7852 |
__dahdi_transmit_chunk(chans[x], data); |
| 7853 |
if (data) |
| 7854 |
__buf_push(&chans[x]->confout, NULL, |
| 7855 |
"conftransmit"); |
| 7856 |
spin_unlock(&chans[x]->lock); |
| 7857 |
} |
| 7858 |
} |
| 7859 |
#ifdef DAHDI_SYNC_TICK |
| 7860 |
for (x = 0; x < maxspans; x++) { |
| 7861 |
struct dahdi_span *const s = spans[x]; |
| 7862 |
if (s && s->sync_tick) |
| 7863 |
s->sync_tick(s, s == master); |
| 7864 |
} |
| 7865 |
#endif |
| 7866 |
read_unlock(&chan_lock); |
| 7867 |
spin_unlock_irqrestore(&bigzaplock, flags); |
| 7868 |
} |
| 7869 |
|
| 7870 |
#ifndef CONFIG_DAHDI_CORE_TIMER |
| 7871 |
|
| 7872 |
static void coretimer_init(void) |
| 7873 |
{ |
| 7874 |
return; |
| 7875 |
} |
| 7876 |
|
| 7877 |
static void coretimer_cleanup(void) |
| 7878 |
{ |
| 7879 |
return; |
| 7880 |
} |
| 7881 |
|
| 7882 |
#else |
| 7883 |
|
| 7884 |
static unsigned long core_diff_ms(struct timespec *t0, struct timespec *t1) |
| 7885 |
{ |
| 7886 |
long nanosec, sec; |
| 7887 |
unsigned long ms; |
| 7888 |
sec = (t1->tv_sec - t0->tv_sec); |
| 7889 |
nanosec = (t1->tv_nsec - t0->tv_nsec); |
| 7890 |
while (nanosec >= NSEC_PER_SEC) { |
| 7891 |
nanosec -= NSEC_PER_SEC; |
| 7892 |
++sec; |
| 7893 |
} |
| 7894 |
while (nanosec < 0) { |
| 7895 |
nanosec += NSEC_PER_SEC; |
| 7896 |
--sec; |
| 7897 |
} |
| 7898 |
ms = (sec * 1000) + (nanosec / 1000000L); |
| 7899 |
return ms; |
| 7900 |
} |
| 7901 |
|
| 7902 |
static void coretimer_func(unsigned long param) |
| 7903 |
{ |
| 7904 |
unsigned long ms_since_start; |
| 7905 |
struct timespec now; |
| 7906 |
const unsigned long MAX_INTERVAL = 100000L; |
| 7907 |
const unsigned long FOURMS_INTERVAL = HZ/250; |
| 7908 |
const unsigned long ONESEC_INTERVAL = HZ; |
| 7909 |
|
| 7910 |
now = current_kernel_time(); |
| 7911 |
|
| 7912 |
if (atomic_read(&core_timer.count) == |
| 7913 |
atomic_read(&core_timer.last_count)) { |
| 7914 |
|
| 7915 |
/* This is the code path if a board driver is not calling |
| 7916 |
* dahdi_receive, and therefore the core of dahdi needs to |
| 7917 |
* perform the master span processing itself. */ |
| 7918 |
|
| 7919 |
if (!atomic_read(&core_timer.shutdown)) |
| 7920 |
mod_timer(&core_timer.timer, jiffies + FOURMS_INTERVAL); |
| 7921 |
|
| 7922 |
ms_since_start = core_diff_ms(&core_timer.start_interval, &now); |
| 7923 |
while (ms_since_start > atomic_read(&core_timer.count)) |
| 7924 |
process_masterspan(); |
| 7925 |
|
| 7926 |
if (ms_since_start > MAX_INTERVAL) { |
| 7927 |
atomic_set(&core_timer.count, 0); |
| 7928 |
atomic_set(&core_timer.last_count, 0); |
| 7929 |
core_timer.start_interval = now; |
| 7930 |
} else { |
| 7931 |
atomic_set(&core_timer.last_count, |
| 7932 |
atomic_read(&core_timer.count)); |
| 7933 |
} |
| 7934 |
|
| 7935 |
} else { |
| 7936 |
|
| 7937 |
/* It looks like a board driver is calling dahdi_receive. We |
| 7938 |
* will just check again in a second. */ |
| 7939 |
atomic_set(&core_timer.count, 0); |
| 7940 |
atomic_set(&core_timer.last_count, 0); |
| 7941 |
core_timer.start_interval = now; |
| 7942 |
if (!atomic_read(&core_timer.shutdown)) |
| 7943 |
mod_timer(&core_timer.timer, jiffies + ONESEC_INTERVAL); |
| 7944 |
} |
| 7945 |
} |
| 7946 |
|
| 7947 |
static void coretimer_init(void) |
| 7948 |
{ |
| 7949 |
init_timer(&core_timer.timer); |
| 7950 |
core_timer.timer.function = coretimer_func; |
| 7951 |
core_timer.start_interval = current_kernel_time(); |
| 7952 |
core_timer.timer.expires = jiffies + HZ; |
| 7953 |
atomic_set(&core_timer.count, 0); |
| 7954 |
atomic_set(&core_timer.shutdown, 0); |
| 7955 |
add_timer(&core_timer.timer); |
| 7956 |
} |
| 7957 |
|
| 7958 |
static void coretimer_cleanup(void) |
| 7959 |
{ |
| 7960 |
atomic_set(&core_timer.shutdown, 1); |
| 7961 |
del_timer_sync(&core_timer.timer); |
| 7962 |
} |
| 7963 |
|
| 7964 |
#endif /* CONFIG_DAHDI_CORE_TIMER */ |
| 7965 |
|
| 7966 |
|
| 7751 |
int dahdi_receive(struct dahdi_span *span) |
7967 |
int dahdi_receive(struct dahdi_span *span) |
| 7752 |
{ |
7968 |
{ |
| 7753 |
int x,y,z; |
7969 |
int x,y,z; |
| 7754 |
unsigned long flags; |
7970 |
unsigned long flags; |
| 7755 |
|
7971 |
|
| 7756 |
#if 1 |
|
|
| 7757 |
#ifdef CONFIG_DAHDI_WATCHDOG |
7972 |
#ifdef CONFIG_DAHDI_WATCHDOG |
| 7758 |
span->watchcounter--; |
7973 |
span->watchcounter--; |
| 7759 |
#endif |
7974 |
#endif |
|
Lines 7833-7919
Link Here
|
| 7833 |
} |
8048 |
} |
| 7834 |
} |
8049 |
} |
| 7835 |
|
8050 |
|
| 7836 |
if (span == master) { |
8051 |
if (span == master) |
| 7837 |
/* Hold the big zap lock for the duration of major |
8052 |
process_masterspan(); |
| 7838 |
activities which touch all sorts of channels */ |
|
|
| 7839 |
spin_lock_irqsave(&bigzaplock, flags); |
| 7840 |
read_lock(&chan_lock); |
| 7841 |
/* Process any timers */ |
| 7842 |
process_timers(); |
| 7843 |
/* If we have dynamic stuff, call the ioctl with 0,0 parameters to |
| 7844 |
make it run */ |
| 7845 |
if (dahdi_dynamic_ioctl) |
| 7846 |
dahdi_dynamic_ioctl(0,0); |
| 7847 |
for (x=1;x<maxchans;x++) { |
| 7848 |
if (chans[x] && chans[x]->confmode && !(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7849 |
u_char *data; |
| 7850 |
spin_lock(&chans[x]->lock); |
| 7851 |
data = __buf_peek(&chans[x]->confin); |
| 7852 |
__dahdi_receive_chunk(chans[x], data); |
| 7853 |
if (data) |
| 7854 |
__buf_pull(&chans[x]->confin, NULL,chans[x], "confreceive"); |
| 7855 |
spin_unlock(&chans[x]->lock); |
| 7856 |
} |
| 7857 |
} |
| 7858 |
/* This is the master channel, so make things switch over */ |
| 7859 |
rotate_sums(); |
| 7860 |
/* do all the pseudo and/or conferenced channel receives (getbuf's) */ |
| 7861 |
for (x=1;x<maxchans;x++) { |
| 7862 |
if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7863 |
spin_lock(&chans[x]->lock); |
| 7864 |
__dahdi_transmit_chunk(chans[x], NULL); |
| 7865 |
spin_unlock(&chans[x]->lock); |
| 7866 |
} |
| 7867 |
} |
| 7868 |
if (maxlinks) { |
| 7869 |
#ifdef CONFIG_DAHDI_MMX |
| 7870 |
dahdi_kernel_fpu_begin(); |
| 7871 |
#endif |
| 7872 |
/* process all the conf links */ |
| 7873 |
for(x = 1; x <= maxlinks; x++) { |
| 7874 |
/* if we have a destination conf */ |
| 7875 |
if (((z = confalias[conf_links[x].dst]) > 0) && |
| 7876 |
((y = confalias[conf_links[x].src]) > 0)) { |
| 7877 |
ACSS(conf_sums[z], conf_sums[y]); |
| 7878 |
} |
| 7879 |
} |
| 7880 |
#ifdef CONFIG_DAHDI_MMX |
| 7881 |
kernel_fpu_end(); |
| 7882 |
#endif |
| 7883 |
} |
| 7884 |
/* do all the pseudo/conferenced channel transmits (putbuf's) */ |
| 7885 |
for (x=1;x<maxchans;x++) { |
| 7886 |
if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7887 |
unsigned char tmp[DAHDI_CHUNKSIZE]; |
| 7888 |
spin_lock(&chans[x]->lock); |
| 7889 |
__dahdi_getempty(chans[x], tmp); |
| 7890 |
__dahdi_receive_chunk(chans[x], tmp); |
| 7891 |
spin_unlock(&chans[x]->lock); |
| 7892 |
} |
| 7893 |
} |
| 7894 |
for (x=1;x<maxchans;x++) { |
| 7895 |
if (chans[x] && chans[x]->confmode && !(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { |
| 7896 |
u_char *data; |
| 7897 |
spin_lock(&chans[x]->lock); |
| 7898 |
data = __buf_pushpeek(&chans[x]->confout); |
| 7899 |
__dahdi_transmit_chunk(chans[x], data); |
| 7900 |
if (data) |
| 7901 |
__buf_push(&chans[x]->confout, NULL, "conftransmit"); |
| 7902 |
spin_unlock(&chans[x]->lock); |
| 7903 |
} |
| 7904 |
} |
| 7905 |
#ifdef DAHDI_SYNC_TICK |
| 7906 |
for (x=0;x<maxspans;x++) { |
| 7907 |
struct dahdi_span *s = spans[x]; |
| 7908 |
|
8053 |
|
| 7909 |
if (s && s->sync_tick) |
|
|
| 7910 |
s->sync_tick(s, s == master); |
| 7911 |
} |
| 7912 |
#endif |
| 7913 |
read_unlock(&chan_lock); |
| 7914 |
spin_unlock_irqrestore(&bigzaplock, flags); |
| 7915 |
} |
| 7916 |
#endif |
| 7917 |
return 0; |
8054 |
return 0; |
| 7918 |
} |
8055 |
} |
| 7919 |
|
8056 |
|
|
Lines 8045-8050
Link Here
|
| 8045 |
#ifdef CONFIG_DAHDI_WATCHDOG |
8182 |
#ifdef CONFIG_DAHDI_WATCHDOG |
| 8046 |
watchdog_init(); |
8183 |
watchdog_init(); |
| 8047 |
#endif |
8184 |
#endif |
|
|
8185 |
coretimer_init(); |
| 8048 |
return res; |
8186 |
return res; |
| 8049 |
} |
8187 |
} |
| 8050 |
|
8188 |
|
|
Lines 8052-8057
Link Here
|
| 8052 |
{ |
8190 |
{ |
| 8053 |
int x; |
8191 |
int x; |
| 8054 |
|
8192 |
|
|
|
8193 |
coretimer_cleanup(); |
| 8194 |
|
| 8055 |
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 253)); /* timer */ |
8195 |
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 253)); /* timer */ |
| 8056 |
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 254)); /* channel */ |
8196 |
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 254)); /* channel */ |
| 8057 |
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 255)); /* pseudo */ |
8197 |
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 255)); /* pseudo */ |