--- dahdi-linux-complete-2.6.1+2.6.1/linux/drivers/dahdi/dahdi-base.c 2012-04-12 00:45:45.000000000 +0700 +++ dahdi-linux-complete/linux/drivers/dahdi/dahdi-base.c 2012-12-05 10:51:16.758663266 +0700 @@ -180,7 +180,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 @@ -3740,31 +3743,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) + !test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags)) continue; - if (!can_provide_timing(s)) - 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 : "no master (core timer)"); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) @@ -7111,7 +7111,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)) { @@ -7142,25 +7141,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; }