--- dahdi-linux/drivers/dahdi/dahdi-base.c 2013-01-17 17:54:19.803393313 +0700 +++ dahdi-linux-pavel/drivers/dahdi/dahdi-base.c 2013-01-18 16:45:29.004077678 +0700 @@ -173,7 +173,7 @@ static sumtype *conf_sums; static sumtype *conf_sums_prev; -static struct dahdi_span *master; +static struct dahdi_span *master = NULL; struct file_operations *dahdi_transcode_fops = NULL; #ifdef CONFIG_DAHDI_CORE_TIMER @@ -3802,31 +3802,28 @@ static void __dahdi_find_master_span(void) { - struct dahdi_span *s; + struct dahdi_span *s, *old_master, *new_master = NULL; unsigned long flags; - struct dahdi_span *old_master; spin_lock_irqsave(&chan_lock, flags); old_master = master; - list_for_each_entry(s, &span_list, spans_node) { - if (s->alarms && old_master) + /* Searching for the FIRST reliable sync source with reverse for. */ + list_for_each_entry_reverse(s, &span_list, spans_node) { + if (!can_provide_timing(s) || s->alarms) continue; if (dahdi_is_digital_span(s) && - !test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags) && - old_master) - continue; - if (!can_provide_timing(s)) + !test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags)) continue; - if (master == s) - continue; - - master = s; - break; + if ((0 == s->channels) && !new_master) /* dummy is better than nothing (coretimer). */ + new_master = s; + new_master = s; /* But real span is better than dummy. */ } + master = new_master; spin_unlock_irqrestore(&chan_lock, flags); if ((debug & DEBUG_MAIN) && (old_master != master)) - module_printk(KERN_NOTICE, "Master changed to %s\n", s->name); + module_printk(KERN_NOTICE, "Master changed to '%s'\n", + master ? master->name : "core_timer"); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) @@ -7250,7 +7247,6 @@ static int _dahdi_unassign_span(struct dahdi_span *span) { int x; - struct dahdi_span *new_master, *s; unsigned long flags; if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) { @@ -7281,25 +7277,7 @@ for (x=0;xchannels;x++) dahdi_chan_unreg(span->chans[x]); - new_master = master; /* FIXME: locking */ - if (master == span) - new_master = NULL; - - spin_lock_irqsave(&chan_lock, flags); - list_for_each_entry(s, &span_list, spans_node) { - if ((s == new_master) || !can_provide_timing(s)) - continue; - new_master = s; - break; - } - spin_unlock_irqrestore(&chan_lock, flags); - if (master != new_master) { - if (debug & DEBUG_MAIN) { - module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__, - (new_master)? new_master->name: "no master"); - } - } - master = new_master; + __dahdi_find_master_span(); return 0; } @@ -9775,6 +9753,7 @@ * dahdi_receive, and therefore the core of dahdi needs to * perform the master span processing itself. */ if (core_timer.dahdi_receive_used) { + master = NULL; core_timer.dahdi_receive_used = 0; dahdi_dbg(GENERAL, "Master changed to core_timer\n"); }