diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 5b99865044..8b0de8508b 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -5433,12 +5433,14 @@ static void execute_safety_hangup(void *data)
 
 FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
 {
+	ftdm_channel_t *fchan = NULL;
 	if (sigmsg->channel) {
-		ftdm_mutex_lock(sigmsg->channel->mutex);
-		sigmsg->chan_id = sigmsg->channel->chan_id;
-		sigmsg->span_id = sigmsg->channel->span_id;
-		sigmsg->call_id = sigmsg->channel->caller_data.call_id;
-		sigmsg->call_priv = sigmsg->channel->caller_data.priv;
+		fchan = sigmsg->channel;
+		ftdm_channel_lock(fchan);
+		sigmsg->chan_id = fchan->chan_id;
+		sigmsg->span_id = fchan->span_id;
+		sigmsg->call_id = fchan->caller_data.call_id;
+		sigmsg->call_priv = fchan->caller_data.priv;
 	}
 	
 	/* some core things to do on special events */
@@ -5447,14 +5449,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 	case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
 		{
 			if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_UP) {
-				ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
-				ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED);
+				ftdm_set_flag(fchan, FTDM_CHANNEL_SIG_UP);
+				ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED);
 			} else {
-				ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
+				ftdm_clear_flag(fchan, FTDM_CHANNEL_SIG_UP);
 				if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_SUSPENDED) {
-					ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED);
+					ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED);
 				} else {
-					ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED);
+					ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED);
 				}
 			}
 		}
@@ -5462,14 +5464,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 
 	case FTDM_SIGEVENT_START:
 		{
-			ftdm_assert(!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED), "Started call twice!");
+			ftdm_assert(!ftdm_test_flag(fchan, FTDM_CHANNEL_CALL_STARTED), "Started call twice!");
 
-			if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_OUTBOUND)) {
-				ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_WARNING, "Inbound call taking over outbound channel\n");
-				ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_OUTBOUND);
+			if (ftdm_test_flag(fchan, FTDM_CHANNEL_OUTBOUND)) {
+				ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "Inbound call taking over outbound channel\n");
+				ftdm_clear_flag(fchan, FTDM_CHANNEL_OUTBOUND);
 			}
-			ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED);
-			ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data);
+			ftdm_set_flag(fchan, FTDM_CHANNEL_CALL_STARTED);
+			ftdm_call_set_call_id(fchan, &fchan->caller_data);
 			/* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was
 			 * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
 			 * is needed at all? */
@@ -5483,8 +5485,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 	case FTDM_SIGEVENT_PROGRESS_MEDIA:
 		{
 			/* test signaling module compliance */
-			if (sigmsg->channel->state != FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
-				ftdm_log_chan(sigmsg->channel, FTDM_LOG_WARNING, "FTDM_SIGEVENT_PROGRESS_MEDIA sent in state %s\n", ftdm_channel_state2str(sigmsg->channel->state));
+			if (fchan->state != FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
+				ftdm_log_chan(fchan, FTDM_LOG_WARNING, "FTDM_SIGEVENT_PROGRESS_MEDIA sent in state %s\n", ftdm_channel_state2str(fchan->state));
 			}
 		}
 		break;
@@ -5492,8 +5494,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 	case FTDM_SIGEVENT_UP:
 		{
 			/* test signaling module compliance */
-			if (sigmsg->channel->state != FTDM_CHANNEL_STATE_UP) {
-				ftdm_log_chan(sigmsg->channel, FTDM_LOG_WARNING, "FTDM_SIGEVENT_UP sent in state %s\n", ftdm_channel_state2str(sigmsg->channel->state));
+			if (fchan->state != FTDM_CHANNEL_STATE_UP) {
+				ftdm_log_chan(fchan, FTDM_LOG_WARNING, "FTDM_SIGEVENT_UP sent in state %s\n", ftdm_channel_state2str(fchan->state));
 			}
 		}
 		break;
@@ -5505,20 +5507,20 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 
 			/* if the call was never started, do not send SIGEVENT_STOP
 			   this happens for FXS devices in ftmod_analog which blindly send SIGEVENT_STOP, we should fix it there ... */
-			if (!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED)) {
-				ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n");
+			if (!ftdm_test_flag(fchan, FTDM_CHANNEL_CALL_STARTED)) {
+				ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n");
 				goto done;
 			}
 
-			if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) {
-				ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
+			if (ftdm_test_flag(fchan, FTDM_CHANNEL_USER_HANGUP)) {
+				ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
 				goto done;
 			}
 
-			if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) {
-				ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
+			if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
+				ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
 				/* if the user does not move us to hangup in 2 seconds, we will do it ourselves */
-				ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer);
+				ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, fchan, &fchan->hangup_timer);
 			}
 		}
 		break;
@@ -5537,8 +5539,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 
 done:
 	
-	if (sigmsg->channel) {
-		ftdm_mutex_unlock(sigmsg->channel->mutex);
+	if (fchan) {
+		ftdm_channel_unlock(fchan);
 	}
 
 	return FTDM_SUCCESS;
diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c
index 57a8fb4830..f2524727ca 100644
--- a/libs/freetdm/src/ftdm_threadmutex.c
+++ b/libs/freetdm/src/ftdm_threadmutex.c
@@ -27,6 +27,7 @@
 #   endif
 #   include <windows.h>
 #endif
+/*#define FTDM_DEBUG_MUTEX 0*/
 
 #include "private/ftdm_core.h"
 #include "ftdm_threadmutex.h"
@@ -46,8 +47,26 @@ struct ftdm_mutex {
 
 #define FTDM_THREAD_CALLING_CONVENTION
 
+#ifdef FTDM_DEBUG_MUTEX
+#define FTDM_MUTEX_MAX_REENTRANCY 30
+typedef struct ftdm_lock_entry {
+	const char *file;
+	const char *func;
+	uint32_t line;
+} ftdm_lock_entry_t;
+
+typedef struct ftdm_lock_history {
+	ftdm_lock_entry_t locked;
+	ftdm_lock_entry_t unlocked;
+} ftdm_lock_history_t;
+#endif
+
 struct ftdm_mutex {
 	pthread_mutex_t mutex;
+#ifdef FTDM_DEBUG_MUTEX
+	ftdm_lock_history_t lock_history[FTDM_MUTEX_MAX_REENTRANCY];
+	uint8_t reentrancy;
+#endif
 };
 
 #endif
@@ -112,7 +131,7 @@ FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached_ex(ftdm_thread_function_t
 	ftdm_thread_t *thread = NULL;
 	ftdm_status_t status = FTDM_FAIL;
 
-	if (!func || !(thread = (ftdm_thread_t *)ftdm_malloc(sizeof(ftdm_thread_t)))) {
+	if (!func || !(thread = (ftdm_thread_t *)ftdm_calloc(1, sizeof(ftdm_thread_t)))) {
 		goto done;
 	}
 
@@ -162,7 +181,7 @@ FT_DECLARE(ftdm_status_t) ftdm_mutex_create(ftdm_mutex_t **mutex)
 #endif
 	ftdm_mutex_t *check = NULL;
 
-	check = (ftdm_mutex_t *)ftdm_malloc(sizeof(**mutex));
+	check = (ftdm_mutex_t *)ftdm_calloc(1, sizeof(**mutex));
 	if (!check)
 		goto done;
 #ifdef WIN32
@@ -209,21 +228,40 @@ FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex)
 	return FTDM_SUCCESS;
 }
 
-FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(ftdm_mutex_t *mutex)
+#define ADD_LOCK_HISTORY(mutex, file, line, func) \
+	{ \
+		if ((mutex)->reentrancy < FTDM_MUTEX_MAX_REENTRANCY) { \
+			(mutex)->lock_history[mutex->reentrancy].locked.file = (file); \
+			(mutex)->lock_history[mutex->reentrancy].locked.func = (func); \
+			(mutex)->lock_history[mutex->reentrancy].locked.line = (line); \
+			(mutex)->lock_history[mutex->reentrancy].unlocked.file = NULL; \
+			(mutex)->lock_history[mutex->reentrancy].unlocked.func = NULL; \
+			(mutex)->lock_history[mutex->reentrancy].unlocked.line = 0; \
+			(mutex)->reentrancy++; \
+			if ((mutex)->reentrancy == FTDM_MUTEX_MAX_REENTRANCY) { \
+				ftdm_log((file), (func), (line), FTDM_LOG_LEVEL_ERROR, "Max reentrancy reached for mutex %p\n", (mutex)); \
+			} \
+		} \
+	}
+
+FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex)
 {
 #ifdef WIN32
 	EnterCriticalSection(&mutex->mutex);
 #else
 	int err;
 	if ((err = pthread_mutex_lock(&mutex->mutex))) {
-		ftdm_log(FTDM_LOG_ERROR, "Failed to lock mutex %d:%s\n", err, strerror(err));
+		ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Failed to lock mutex %d:%s\n", err, strerror(err));
 		return FTDM_FAIL;
 	}
+#endif
+#ifdef FTDM_DEBUG_MUTEX
+	ADD_LOCK_HISTORY(mutex, file, line, func);
 #endif
 	return FTDM_SUCCESS;
 }
 
-FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(ftdm_mutex_t *mutex)
+FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex)
 {
 #ifdef WIN32
 	if (!TryEnterCriticalSection(&mutex->mutex))
@@ -231,17 +269,43 @@ FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(ftdm_mutex_t *mutex)
 #else
 	if (pthread_mutex_trylock(&mutex->mutex))
 		return FTDM_FAIL;
+#endif
+#ifdef FTDM_DEBUG_MUTEX
+	ADD_LOCK_HISTORY(mutex, file, line, func);
 #endif
 	return FTDM_SUCCESS;
 }
 
-FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(ftdm_mutex_t *mutex)
+FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex)
 {
+#ifdef FTDM_DEBUG_MUTEX
+	int i = 0;
+	if (mutex->reentrancy == 0) {
+		ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Cannot unlock something that is not locked!\n");
+		return FTDM_FAIL;
+	}
+	i = mutex->reentrancy - 1;
+	/* I think this is a fair assumption when debugging */
+	if (func != mutex->lock_history[i].locked.func) {
+		ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Mutex %p was suspiciously locked at %s->%s:%d but unlocked at %s->%s:%d!\n",
+				mutex, mutex->lock_history[i].locked.func, mutex->lock_history[i].locked.file, mutex->lock_history[i].locked.line, 
+				func, file, line);
+	}
+	mutex->lock_history[i].unlocked.file = file;
+	mutex->lock_history[i].unlocked.line = line;
+	mutex->lock_history[i].unlocked.func = func;
+	mutex->reentrancy--;
+#endif
 #ifdef WIN32
 	LeaveCriticalSection(&mutex->mutex);
 #else
-	if (pthread_mutex_unlock(&mutex->mutex))
+	if (pthread_mutex_unlock(&mutex->mutex)) {
+		ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Failed to unlock mutex: %s\n", strerror(errno));
+#ifdef FTDM_DEBUG_MUTEX
+		mutex->reentrancy++;
+#endif
 		return FTDM_FAIL;
+	}
 #endif
 	return FTDM_SUCCESS;
 }
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
index 710b0c37a6..5f87ffd877 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
@@ -1618,13 +1618,19 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c
 /******************************************************************************/
 static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose)
 {
-	int					x;
-	sngss7_chan_data_t	*sngss7_info;
-	ftdm_channel_t		*ftdmchan;
-	sngss7_span_data_t	*sngss7_span;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_span_data_t *sngss7_span = NULL;
+	int x = 0;
+	int basefound = 0;
 
 	if (range > 31) {
-		stream->write_function(stream, "Invalid range value %d", range);
+		stream->write_function(stream, "Range value %d is too big for a GRS", range);
+		return FTDM_SUCCESS;
+	}
+
+	if (range < 2) {
+		stream->write_function(stream, "Range value %d is too small for a GRS", range);
 		return FTDM_SUCCESS;
 	}
 
@@ -1638,42 +1644,45 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
 
 			if ((ftdmchan->physical_span_id == span) && 
 				((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
+
 				/* now that we have the right channel...put a lock on it so no-one else can use it */
-				ftdm_mutex_lock(ftdmchan->mutex);
+				ftdm_channel_lock(ftdmchan);
+
+				/* if another reset is still in progress, skip this channel */
+				if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX)) {
+					ftdm_channel_unlock(ftdmchan);
+					continue;
+				}
 
 				/* check if there is a pending state change|give it a bit to clear */
 				if (check_for_state_change(ftdmchan)) {
 					SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-					/* check if we need to die */
-					SS7_ASSERT;
-					/* unlock the channel again before we exit */
-					ftdm_mutex_unlock(ftdmchan->mutex);
-					/* move to the next channel */
+					ftdm_channel_unlock(ftdmchan);
 					continue;
-				} else {
-					/* throw the grp reset flag */
-					sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
-					if (ftdmchan->physical_chan_id == chan) {
-						sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE);
-						sngss7_span->tx_grs.circuit = sngss7_info->circuit->id;
-						sngss7_span->tx_grs.range = range-1;
-					}
-
-					/* set the channel to suspended state */
-					ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-
 				}
 
-				/* unlock the channel again before we exit */
-				ftdm_mutex_unlock(ftdmchan->mutex);
+				/* throw the grp reset flag */
+				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
+				if (!basefound) {
+					ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Setting channel as GRS base\n");
+					sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+					sngss7_info->tx_grs.circuit = sngss7_info->circuit->id;
+					sngss7_info->tx_grs.range = range - 1;
+					basefound = 1;
+				}
 
-			} /* if ( span and chan) */
+				/* set the channel to restart state */
+				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 
-		} /* if ( cic != 0) */
+				ftdm_channel_unlock(ftdmchan);
+
+			}
+
+		}
 
 		/* go the next circuit */
 		x++;
-	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+	}
 	
 	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
index 48a842c37c..20e9a1261c 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
@@ -1910,11 +1910,10 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 {
 	SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-	sngss7_chan_data_t	*sngss7_info = NULL;
-	ftdm_channel_t		*ftdmchan = NULL;
-	sngss7_span_data_t	*sngss7_span = NULL; 
-	int					range;
-
+	sngss7_chan_data_t *sngss7_info = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_span_data_t *sngss7_span = NULL;
+	int range = 0;
 
 	/* confirm that the circuit is voice channel */
 	if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@@ -1948,9 +1947,15 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 
 	/* fill in the span structure for this circuit */
 	sngss7_span = ftdmchan->span->signal_data;
-	sngss7_span->rx_grs.circuit = circuit; 
-	sngss7_span->rx_grs.range = range;
+	if (sngss7_info->rx_grs.range) {
+		SS7_CRITICAL("Cannot handle another GRS on CIC = %d\n", sngss7_info->circuit->cic);
+		SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+		return FTDM_FAIL;
+	}
+	sngss7_info->rx_grs.circuit = circuit; 
+	sngss7_info->rx_grs.range = range;
 
+	ftdm_set_flag(sngss7_span, SNGSS7_RX_GRS_PENDING);
 	/* the reset will be started in the main thread by "check_if_rx_grs_started" */
 
 	SS7_FUNC_TRACE_EXIT(__FUNCTION__);
@@ -1962,10 +1967,10 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 {
 	SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-	sngss7_chan_data_t	*sngss7_info = NULL;
-	ftdm_channel_t		*ftdmchan = NULL;
-	sngss7_span_data_t	*sngss7_span = NULL; 
-	int					range;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_span_data_t *sngss7_span = NULL; 
+	int range = 0;
 
 	/* confirm that the circuit is voice channel */
 	if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@@ -1999,17 +2004,24 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 
 	/* fill in the span structure for this circuit */
 	sngss7_span = ftdmchan->span->signal_data;
-	sngss7_span->rx_gra.circuit = circuit; 
-	sngss7_span->rx_gra.range = range;
+	if (sngss7_info->rx_gra.range) {
+		SS7_ERROR("Cannot handle another GRA on CIC = %d\n", sngss7_info->circuit->cic);
+		SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+		return FTDM_FAIL;
+	}
+	sngss7_info->rx_gra.circuit = circuit; 
+	sngss7_info->rx_gra.range = range;
 
 	/* check if there is a cause value in the GRA */
 	if ((siStaEvnt != NULL) &&
 		(siStaEvnt->causeDgn.eh.pres == PRSNT_NODEF) &&
 		(siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) {
 
-		sngss7_span->rx_gra.cause = siStaEvnt->causeDgn.causeVal.val;
+		sngss7_info->rx_gra.cause = siStaEvnt->causeDgn.causeVal.val;
 	}
 
+	ftdm_set_flag(sngss7_span, SNGSS7_RX_GRA_PENDING);
+
 	/* the reset will be started in the main thread by "check_if_rx_gra_started" */
 	
 	SS7_FUNC_TRACE_EXIT(__FUNCTION__);
@@ -2121,9 +2133,12 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
 {
 	SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-	sngss7_chan_data_t	*sngss7_info = NULL;
-	sngss7_span_data_t	*sngss7_span = NULL;
-	ftdm_channel_t		*ftdmchan = NULL;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	sngss7_span_data_t *sngss7_span = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
 
 
 	/* confirm that the circuit is voice channel */
@@ -2147,13 +2162,28 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
 			DECODE_LCC_EVENT(evntType));
 	}
 
-	/* check if we just sent a GRS request...*/
+	/* find out if the cic belongs to one of our GRS requests, if so, 
+	 * all circuits in the request must be blocked */
 	sngss7_span = ftdmchan->span->signal_data;
-	if (sngss7_span->tx_grs.circuit > 0) {
-		/* we need to put all circuits on this UCIC */
-		sngss7_span->ucic.circuit = sngss7_span->tx_grs.circuit;
-		sngss7_span->ucic.range = sngss7_span->tx_grs.range;
-		goto done;
+	iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL);
+	curr = iter;
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
+
+		ftdm_channel_lock(fchan);
+
+		cinfo = fchan->call_data;
+		if (circuit == cinfo->tx_grs.circuit) {
+			cinfo->ucic.circuit = cinfo->tx_grs.circuit;
+			cinfo->ucic.range = cinfo->tx_grs.range;
+			ftdm_set_flag(sngss7_span, SNGSS7_UCIC_PENDING);
+
+			ftdm_channel_unlock(fchan);
+
+			goto done;
+		}
+
+		ftdm_channel_unlock(fchan);
 	}
 
 	/* lock the channel */
@@ -2168,6 +2198,10 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
 	/* unlock the channel again before we exit */
 	ftdm_mutex_unlock(ftdmchan->mutex);
 done:
+	if (iter) {
+		ftdm_iterator_free(iter);
+	}
+
 	SS7_FUNC_TRACE_EXIT(__FUNCTION__);
 	return FTDM_SUCCESS;
 }
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index e4b9bab8c0..cc922617af 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -328,13 +328,13 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
  
 				/* unlock the channel */
 				ftdm_mutex_unlock (ftdmchan->mutex);				
-			}/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans)))  */
+			}
 
 			/* clean out all pending stack events */
 			while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) {
 				ftdm_sangoma_ss7_process_stack_event(sngss7_event);
 				ftdm_safe_free(sngss7_event);
-			}/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */
+			}
 
 			/* signal the core that sig events are queued for processing */
 			ftdm_span_trigger_signals(ftdmspan);
@@ -356,27 +356,27 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 
 			break;
 		/**********************************************************************/
-		} /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */
+		}
 
 		/* check if there is a GRA to proccess on the span */
-		if (sngss7_span->rx_gra.range > 0) {
+		if (ftdm_test_flag(sngss7_span, SNGSS7_RX_GRA_PENDING)) {
 			check_if_rx_gra_started(ftdmspan);
-		} /* if (sngss7->span->rx_gra.range > 0) */
+		}
 
 		/* check if there is a GRS being processed on the span */
-		if (sngss7_span->rx_grs.range > 0) {
+		if (ftdm_test_flag(sngss7_span, SNGSS7_RX_GRS_PENDING)) {
 			/* check if the rx_grs has started */
 			check_if_rx_grs_started(ftdmspan);
 
 			/* check if the rx_grs has cleared */
 			check_if_rx_grs_processed(ftdmspan);
-		} /* if (sngss7_span->rx_grs.range > 0) */
+		}
 
 		/* check if there is a UCIC to be processed on the span */
-		if (sngss7_span->ucic.range > 0) {
+		if (ftdm_test_flag(sngss7_span, SNGSS7_UCIC_PENDING)) {
 			/* process the span wide UCIC */
 			process_span_ucic(ftdmspan);
-		} /* if (sngss7_span->ucic.range > 0) */
+		}
 
 		/* check each channel on the span to see if there is an un-procressed SUS/RES flag */
 		check_for_res_sus_flag(ftdmspan);
@@ -398,8 +398,8 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 		default:
 			SS7_ERROR("%s:Failed to poll span event\n", ftdmspan->name);
 		/**********************************************************************/
-		} /* switch (ftdm_span_poll_event(span, 0)) */
-	} /* master while loop */
+		}
+	}
 
 	/* clear the IN_THREAD flag so that we know the thread is done */
 	ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
@@ -423,8 +423,8 @@ ftdm_sangoma_ss7_run_exit:
 /******************************************************************************/
 static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event)
 {
-	sngss7_chan_data_t  *sngss7_info ;
-	ftdm_channel_t	  *ftdmchan;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
 
 	/* get the ftdmchan and ss7_chan_data from the circuit */
 	if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) {
@@ -432,8 +432,8 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
 		return;
 	}
 
-	/* now that we have the right channel...put a lock on it so no-one else can use it */
-	ftdm_mutex_lock(ftdmchan->mutex);
+	/* now that we have the right channel ... put a lock on it so no-one else can use it */
+	ftdm_channel_lock(ftdmchan);
 
 	/* while there's a state change present on this channel process it */
 	ftdm_channel_advance_states(ftdmchan);
@@ -496,24 +496,23 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
 		SS7_ERROR("Unknown Event Id!\n");
 		break;
 	/**************************************************************************/
-	} /* switch (sngss7_event->event_id) */
+	}
 
 	/* while there's a state change present on this channel process it */
 	ftdm_channel_advance_states(ftdmchan);
 
 	/* unlock the channel */
-	ftdm_mutex_unlock(ftdmchan->mutex);
+	ftdm_channel_unlock(ftdmchan);
 
-	return;
 }
 
 /******************************************************************************/
 ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 {
-	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
-	sng_isup_inf_t		*isup_intf = NULL;
-	int					state_flag = 1; 
-	int 				i = 0;
+	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+	sng_isup_inf_t *isup_intf = NULL;
+	int state_flag = 1; 
+	int i = 0;
 
 	SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state));
 
@@ -807,7 +806,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
 			/* clear the reset flag  */
 			clear_rx_rsc_flags(sngss7_info);
-		} /* if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) */
+		}
 
 		/* check if there was a GRS that needs a GRA */
 		if ((sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
@@ -815,10 +814,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) {
 
 			/* check if this is the base circuit and send out the GRA
-			 * we insure that this is the last circuit to have the state change queued
-			 */
-			sngss7_span_data_t *span = ftdmchan->span->signal_data;
-			if (span->rx_grs.circuit == sngss7_info->circuit->id) {
+			 * we insure that this is the last circuit to have the state change queued */
+			if (sngss7_info->rx_grs.range) {
 				/* send out the GRA */
 				ft_to_sngss7_gra(ftdmchan);
 
@@ -828,21 +825,22 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
 			/* clear the grp reset flag */
 			clear_rx_grs_flags(sngss7_info);
-		}/*  if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */
+		}
 
 		/* check if we got the reset response */
 		if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
 			/* clear the reset flag  */
 			clear_tx_rsc_flags(sngss7_info);
-		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) */
+		}
 
 		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
 			/* clear the reset flag  */
 			clear_tx_grs_flags(sngss7_info);
-			
-			/* clean out the spans GRA structure */
-			clear_rx_gra_data(sngss7_info);
-		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) */
+			if (sngss7_info->rx_gra.range) {
+				/* clean out the spans GRA structure */
+				clear_rx_gra_data(sngss7_info);
+			}
+		}
 
 		/* check if we came from reset (aka we just processed a reset) */
 		if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || 
@@ -900,7 +898,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			ftdm_channel_t *close_chan = ftdmchan;
 			/* close the channel */
 			ftdm_channel_close (&close_chan);
-		} /* if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) */
+		}
 
 		/* check if there is a glared call that needs to be processed */
 		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) {
@@ -918,8 +916,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
 				/* clear the glare info */
 				memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
-			} /* if (sngss7_info->glare.circuit != 0) */
-		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) */
+			}
+		}
 
 		break;
 	/**************************************************************************/
@@ -964,9 +962,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
 				/* send out the grs */
 				ft_to_sngss7_grs (ftdmchan);
-				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT);
 
-		}/* if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */
+		}
 	
 		/* if the sig_status is up...bring it down */
 		if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
@@ -1265,13 +1262,12 @@ suspend_goto_restart:
 		
 		break;
 	/**************************************************************************/
-	}/*switch (ftdmchan->state) */
-#if 1
+	}
+
 	if (state_flag) {
 		/* clear the state change flag...since we might be setting a new state */
 		ftdm_channel_complete_state(ftdmchan);
 	}
-#endif
 	return FTDM_SUCCESS;
 }
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
index e4a7bf1cc0..e61f1ee6df 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
@@ -423,7 +423,7 @@ typedef struct sng_ss7_cfg {
 	sng_isup_ckt_t		isupCkt[10000]; 	/* KONRAD - only need 2000 ( and 0-1000 aren't used) since other servers are registerd else where */
 	sng_nsap_t			nsap[MAX_NSAPS+1];
 	sng_isap_t			isap[MAX_ISAPS+1];	
-}sng_ss7_cfg_t;
+} sng_ss7_cfg_t;
 
 typedef struct ftdm_sngss7_data {
 	sng_ss7_cfg_t		cfg;
@@ -433,7 +433,7 @@ typedef struct ftdm_sngss7_data {
 	int					message_trace;
 	int					message_trace_level;
 	fio_signal_cb_t		sig_cb;
-}ftdm_sngss7_data_t;
+} ftdm_sngss7_data_t;
 
 typedef struct sngss7_timer_data {
 	ftdm_timer_id_t			hb_timer_id;
@@ -442,13 +442,13 @@ typedef struct sngss7_timer_data {
 	ftdm_sched_callback_t	callback;
 	ftdm_sched_t			*sched;
 	void					*sngss7_info;
-}sngss7_timer_data_t;
+} sngss7_timer_data_t;
 
 typedef struct sngss7_glare_data {
 	uint32_t				spInstId; 
 	uint32_t				circuit; 
 	SiConEvnt				iam;
-}sngss7_glare_data_t;
+} sngss7_glare_data_t;
 
 typedef struct sngss7_group_data {
 	uint32_t				circuit;
@@ -456,7 +456,7 @@ typedef struct sngss7_group_data {
 	uint8_t					status[255];
 	uint8_t					type;
 	uint8_t					cause;
-}sngss7_group_data_t;
+} sngss7_group_data_t;
 
 typedef struct sngss7_chan_data {
 	ftdm_channel_t			*ftdmchan;
@@ -473,20 +473,24 @@ typedef struct sngss7_chan_data {
 	void					*raw_data;		/* send on next sigevent */
 	sngss7_glare_data_t		glare;
 	sngss7_timer_data_t		t35;
-}sngss7_chan_data_t;
-
-typedef struct sngss7_span_data {
-	ftdm_sched_t			*sched;
 	sngss7_group_data_t		rx_grs;
 	sngss7_group_data_t		rx_gra;
 	sngss7_group_data_t		tx_grs;
+	sngss7_group_data_t		ucic;
+} sngss7_chan_data_t;
+
+#define SNGSS7_RX_GRS_PENDING (1 << 0)
+#define SNGSS7_UCIC_PENDING (1 << 1)
+#define SNGSS7_RX_GRA_PENDING (1 << 2)
+typedef struct sngss7_span_data {
+	ftdm_sched_t			*sched;
+	uint32_t                        flags;
 	sngss7_group_data_t		rx_cgb;
 	sngss7_group_data_t		tx_cgb;
 	sngss7_group_data_t		rx_cgu;
 	sngss7_group_data_t		tx_cgu;
-	sngss7_group_data_t		ucic;
 	ftdm_queue_t 			*event_queue;
-}sngss7_span_data_t;
+} sngss7_span_data_t;
 
 typedef struct sngss7_event_data
 {
@@ -848,7 +852,6 @@ ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
 ftdm_status_t copy_tknStr_to_sngss7(char* str, TknStr *tknStr, TknU8 *oddEven);
 
 int check_for_state_change(ftdm_channel_t *ftdmchan);
-int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
 int check_for_reset(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
 unsigned long get_unique_id(void);
@@ -887,6 +890,7 @@ ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data
 
 /* in ftmod_sangoma_ss7_timers.c */
 void handle_isup_t35(void *userdata);
+
 /******************************************************************************/
 
 /* MACROS *********************************************************************/
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
index 47249c2f5a..56238abdf9 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
@@ -39,32 +39,6 @@
 
 /* GLOBALS ********************************************************************/
 
-/* PROTOTYPES *****************************************************************/
-void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_acm(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_anm(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_rel(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_rlc(ftdm_channel_t * ftdmchan);
-
-void ft_to_sngss7_rsc(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_rsca(ftdm_channel_t * ftdmchan);
-
-void ft_to_sngss7_blo(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_bla(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_ubl(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_uba(ftdm_channel_t * ftdmchan);
-
-void ft_to_sngss7_lpa(ftdm_channel_t * ftdmchan);
-
-void ft_to_sngss7_gra(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_grs(ftdm_channel_t * ftdmchan);
-
-void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan);
-
-void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan);
-void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan);
-
 /* FUNCTIONS ******************************************************************/
 void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 {	
@@ -447,7 +421,6 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
 {
 	SS7_FUNC_TRACE_ENTER (__FUNCTION__);
 	
-	sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
 	SiStaEvnt	gra;
 	
@@ -458,11 +431,11 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
 
 	/* fill in the range */	
 	gra.rangStat.range.pres = PRSNT_NODEF;
-	gra.rangStat.range.val = sngss7_span->rx_grs.range;
+	gra.rangStat.range.val = sngss7_info->rx_grs.range;
 
 	/* fill in the status */
 	gra.rangStat.status.pres = PRSNT_NODEF;
-	gra.rangStat.status.len = ((sngss7_span->rx_grs.range + 1) >> 3) + (((sngss7_span->rx_grs.range + 1) & 0x07) ? 1 : 0); 
+	gra.rangStat.status.len = ((sngss7_info->rx_grs.range + 1) >> 3) + (((sngss7_info->rx_grs.range + 1) & 0x07) ? 1 : 0); 
 	
 	/* the status field should be 1 if blocked for maintenace reasons 
 	* and 0 is not blocked....since we memset the struct nothing to do
@@ -472,15 +445,15 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
 	sng_cc_sta_request (1,
 						0,
 						0,
-						sngss7_span->rx_grs.circuit,
+						sngss7_info->rx_grs.circuit,
 						0,
 						SIT_STA_GRSRSP,
 						&gra);
 	
-	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRA (%d:%d)\n",
+	SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx GRA (%d:%d)\n",
 							sngss7_info->circuit->cic,
 							sngss7_info->circuit->cic,
-							(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
+							(sngss7_info->circuit->cic + sngss7_info->rx_grs.range));
 	
 
 	SS7_FUNC_TRACE_EXIT (__FUNCTION__);
@@ -488,37 +461,40 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
 }
 
 /******************************************************************************/
-void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
+void ft_to_sngss7_grs (ftdm_channel_t *fchan)
 {
 	SS7_FUNC_TRACE_ENTER (__FUNCTION__);
 	
-	sngss7_span_data_t 	*sngss7_span = ftdmchan->span->signal_data;
-	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+	sngss7_chan_data_t *cinfo = fchan->call_data;
 	
 	SiStaEvnt grs;
 	
-	memset (&grs, 0x0, sizeof(grs));
-	
-	grs.rangStat.eh.pres	= PRSNT_NODEF;
-	grs.rangStat.range.pres	= PRSNT_NODEF;
-	grs.rangStat.range.val	= sngss7_span->tx_grs.range;
-	
-	sng_cc_sta_request (1,
-						0,
-						0,
-						sngss7_span->tx_grs.circuit,
-						0,
-						SIT_STA_GRSREQ,
-						&grs);
-	
-	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRS (%d:%d)\n",
-							sngss7_info->circuit->cic,
-							sngss7_info->circuit->cic,
-							(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
+	ftdm_assert(sngss7_test_ckt_flag(cinfo, FLAG_GRP_RESET_TX) && 
+		   !sngss7_test_ckt_flag(cinfo, FLAG_GRP_RESET_SENT), "Incorrect flags\n");
 
+	memset (&grs, 0x0, sizeof(grs));
+	grs.rangStat.eh.pres    = PRSNT_NODEF;
+	grs.rangStat.range.pres = PRSNT_NODEF;
+	grs.rangStat.range.val  = cinfo->tx_grs.range;
+
+	sng_cc_sta_request (1,
+		0,
+		0,
+		cinfo->tx_grs.circuit,
+		0,
+		SIT_STA_GRSREQ,
+		&grs);
+
+	SS7_INFO_CHAN(fchan, "[CIC:%d]Tx GRS (%d:%d)\n",
+		cinfo->circuit->cic,
+		cinfo->circuit->cic,
+		(cinfo->circuit->cic + cinfo->tx_grs.range));
+
+	memset(&cinfo->tx_grs, 0, sizeof(cinfo->tx_grs));
+
+	sngss7_set_ckt_flag(cinfo, FLAG_GRP_RESET_SENT);
 
 	SS7_FUNC_TRACE_EXIT (__FUNCTION__);
-return;
 }
 
 /******************************************************************************/
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
index 3c07f82933..a9029d45e4 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
@@ -47,7 +47,6 @@ uint32_t sngss7_id;
 
 /* PROTOTYPES *****************************************************************/
 int check_for_state_change(ftdm_channel_t *ftdmchan);
-int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
 int check_for_reset(sngss7_chan_data_t *sngss7_info);
 
 unsigned long get_unique_id(void);
@@ -61,14 +60,6 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan);
 
 ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan);
 
-ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info);
-ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info);
-ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info);
-ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info);
-ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info);
-ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info);
-ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
-
 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
 
@@ -862,45 +853,6 @@ int check_for_state_change(ftdm_channel_t *ftdmchan)
 	return 0;
 }
 
-/******************************************************************************/
-int check_cics_in_range(sngss7_chan_data_t *sngss7_info)
-{
-
-
-#if 0
-	ftdm_channel_t		*tmp_ftdmchan;
-	sngss7_chan_data_t  *tmp_sngss7_info;
-	int 				i = 0;
-	
-	/* check all the circuits in the range to see if we are the last ckt to reset */
-	for ( i = sngss7_info->grs.circuit; i < ( sngss7_info->grs.range + 1 ); i++ ) {
-		if ( g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0 ) {
-		
-			/* get the ftdmchan and ss7_chan_data from the circuit */
-			if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCircuit[i].id, &tmp_sngss7_info, &tmp_ftdmchan)) {
-				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCircuit[i].id);
-				return 0;
-			}
-
-			/* check if the channel still has the reset flag done is up */
-			if (!sngss7_test_ckt_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) {
-				SS7_DEBUG_CHAN(tmp_ftdmchan, "[CIC:%d] Still processing reset...\n", tmp_sngss7_info->circuit->cic);
-				return 0;
-			}
-		} /* if not siglink */
-	} /* for */
-
-	SS7_DEBUG("All circuits out of reset: circuit=%d, range=%d\n",
-				sngss7_info->grs.circuit,
-				sngss7_info->grs.range);
-	return 1;
-
-#endif
-
-	return 0;
-
-}
-
 /******************************************************************************/
 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan)
 {
@@ -909,13 +861,19 @@ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_in
 		return FTDM_FAIL;
 	}
 
-	ftdm_assert_return(g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
+	if (!g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj) {
+		SS7_ERROR("No ss7 info for circuit #%d\n", circuit);
+		return FTDM_FAIL;
+	}
 
 	*sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj;
 
-	ftdm_assert_return((*sngss7_info)->ftdmchan, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
-	*ftdmchan = (*sngss7_info)->ftdmchan;
+	if (!(*sngss7_info)->ftdmchan) {
+		SS7_ERROR("No channel for circuit #%d\n", circuit);
+		return FTDM_FAIL;
+	}
 
+	*ftdmchan = (*sngss7_info)->ftdmchan;
 	return FTDM_SUCCESS;
 }
 
@@ -961,67 +919,86 @@ unsigned long get_unique_id(void)
 /******************************************************************************/
 ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
 {
-	ftdm_channel_t 		*ftdmchan = NULL;
-	sngss7_chan_data_t  *sngss7_info = NULL;
-	sngss7_span_data_t	*sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
-	int 				i;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	int i = 0;
 
+	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
 
-	SS7_INFO("Rx GRS (%d:%d)\n", 
-				g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic, 
-				(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range));
+		ftdm_channel_lock(fchan);
+	
+		cinfo = fchan->call_data;
 
-	for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
-
-		/* confirm this is a voice channel, otherwise we do nothing */ 
-		if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
-			continue;
-		} 
-
-		/* extract the channel in question */
-		if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-			SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+		if (!cinfo->rx_grs.range) {
+			ftdm_channel_unlock(fchan);
 			continue;
 		}
 
-		/* check if the GRP_RESET_RX flag is already up */
-		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
-			/* we have already processed this channel...move along */
-			continue;
+		SS7_INFO("Rx GRS (%d:%d)\n", 
+				g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic, 
+				(g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic + cinfo->rx_grs.range));
+
+		for (i = cinfo->rx_grs.circuit; i < (cinfo->rx_grs.circuit + cinfo->rx_grs.range + 1); i++) {
+
+			/* confirm this is a voice channel, otherwise we do nothing */ 
+			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
+				continue;
+			} 
+
+			/* extract the channel in question */
+			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+				continue;
+			}
+
+			/* check if the GRP_RESET_RX flag is already up */
+			if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
+				/* we have already processed this channel...move along */
+				continue;
+			}
+
+			/* lock the channel */
+			ftdm_channel_lock(ftdmchan);
+
+			/* clear up any pending state changes */
+			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+				ftdm_sangoma_ss7_process_state_change (ftdmchan);
+			}
+
+			/* flag the channel as having received a reset */
+			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX);
+
+			switch (ftdmchan->state) {
+			/**************************************************************************/
+			case FTDM_CHANNEL_STATE_RESTART:
+
+				/* go to idle so that we can redo the restart state*/
+				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+
+				break;
+			/**************************************************************************/
+			default:
+
+				/* set the state of the channel to restart...the rest is done by the chan monitor */
+				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+				break;
+			/**************************************************************************/
+			}
+
+			/* unlock the channel again before we exit */
+			ftdm_channel_unlock(ftdmchan);
+
 		}
 
-		/* lock the channel */
-		ftdm_mutex_lock(ftdmchan->mutex);
+		ftdm_channel_unlock(fchan);
+	}
 
-		/* clear up any pending state changes */
-		while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-			ftdm_sangoma_ss7_process_state_change (ftdmchan);
-		}
-
-		/* flag the channel as having received a reset */
-		sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX);
-
-		switch (ftdmchan->state) {
-		/**************************************************************************/
-		case FTDM_CHANNEL_STATE_RESTART:
-
-			/* go to idle so that we can redo the restart state*/
-			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
-
-			break;
-		/**************************************************************************/
-		default:
-
-			/* set the state of the channel to restart...the rest is done by the chan monitor */
-			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-			break;
-		/**************************************************************************/
-		} /* switch (ftdmchan->state) */
-
-		/* unlock the channel again before we exit */
-		ftdm_mutex_unlock(ftdmchan->mutex);
-
-	} /* for (chans in GRS */
+	ftdm_iterator_free(iter);
 
 	return FTDM_SUCCESS;
 }
@@ -1029,191 +1006,249 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
 /******************************************************************************/
 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
 {
-	ftdm_channel_t 		*ftdmchan = NULL;
-	sngss7_chan_data_t  *sngss7_info = NULL;
-	sngss7_span_data_t	*sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
-	int 				i;
-	int					byte = 0;
-	int					bit = 0;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	int i = 0, bn = 0;
+	int byte = 0, bit = 0;
+	int cic_start = 0, cic_end = 0, num_cics = 0;
+	ftdm_bitmap_t *lockmap = 0;
+	ftdm_size_t mapsize = 0;
 
-	/* check all the circuits in the range to see if they are done resetting */
-	for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
+	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
+
+		ftdm_channel_lock(fchan);
+
+		cinfo = fchan->call_data;
+
+		if (!cinfo->rx_grs.range) {
+
+			ftdm_channel_unlock(fchan);
 
-		/* confirm this is a voice channel, otherwise we do nothing */ 
-		if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
 			continue;
 		}
 
-		/* extract the channel in question */
-		if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-			SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
-			continue;
+		cic_start = cinfo->rx_grs.circuit;
+		cic_end = cinfo->rx_grs.circuit + cinfo->rx_grs.range;
+		num_cics = cinfo->rx_grs.range + 1;
+		mapsize = (num_cics / FTDM_BITMAP_NBITS) + 1;
+
+		lockmap = ftdm_calloc(mapsize, sizeof(*lockmap));
+		if (!lockmap) {
+			ftdm_channel_unlock(fchan);
+			return FTDM_ENOMEM;
 		}
 
-		/* lock the channel */
-		ftdm_mutex_lock(ftdmchan->mutex);
+		/* check all the circuits in the range to see if they are done resetting */
+		for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) {
 
-		/* check if there is a state change pending on the channel */
-		if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-			/* check the state to the GRP_RESET_RX_DN flag */
-			if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
-				/* this channel is still resetting...do nothing */
+			/* confirm this is a voice channel, otherwise we do nothing */ 
+			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
+				continue;
+			}
+
+			/* extract the channel in question */
+			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+				ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n");
+				continue;
+			}
+
+			/* lock the channel */
+			ftdm_channel_lock(ftdmchan);
+			ftdm_map_set_bit(lockmap, bn);
+
+			/* check if there is a state change pending on the channel */
+			if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+				/* check the state to the GRP_RESET_RX_DN flag */
+				if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
+					/* this channel is still resetting...do nothing */
 					goto GRS_UNLOCK_ALL;
-			} /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
-		} else {
-			/* state change pending */
-			goto GRS_UNLOCK_ALL;
-		}
-	} /* for ( i = circuit; i < (circuit + range + 1); i++) */
+				} /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
+			} else {
+				/* state change pending */
+				goto GRS_UNLOCK_ALL;
+			}
 
-	SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
-					sngss7_span->rx_grs.circuit,
-					sngss7_span->rx_grs.range);
-
-	/* check all the circuits in the range to see if they are done resetting */
-	for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
-
-		/* confirm this is a voice channel, otherwise we do nothing */ 
-		if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
-			continue;
 		}
 
-		/* extract the channel in question */
-		if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-			SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
-			/* check if we need to die */
-			SS7_ASSERT;
-			/* move along */
-			continue;
+		SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", cinfo->rx_grs.circuit, cinfo->rx_grs.range);
+		for (i = cic_start; i <= cic_end; i++) {
+
+			/* confirm this is a voice channel, otherwise we do nothing */ 
+			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
+				continue;
+			}
+
+			/* extract the channel in question */
+			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
+				ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n");
+				continue;
+			}
+
+			/* throw the GRP reset flag complete flag */
+			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
+
+			/* move the channel to the down state */
+			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+			/* update the status map if the ckt is in blocked state */
+			if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
+				(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
+				(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
+				(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+			
+				cinfo->rx_grs.status[byte] = (cinfo->rx_grs.status[byte] | (1 << bit));
+			}
+
+			/* update the bit and byte counter*/
+			bit ++;
+			if (bit == 8) {
+				byte++;
+				bit = 0;
+			}
+
 		}
-
-		/* throw the GRP reset flag complete flag */
-		sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
-
-		/* move the channel to the down state */
-		ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
-		/* update the status map if the ckt is in blocked state */
-		if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
-			(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
-			(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
-			(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
-		
-			sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
-		} /* if blocked */
-		
-		/* update the bit and byte counter*/
-		bit ++;
-		if (bit == 8) {
-			byte++;
-			bit = 0;
-		}
-	} /* for ( i = circuit; i < (circuit + range + 1); i++) */
-
 GRS_UNLOCK_ALL:
-	for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
+		for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) {
+			/* confirm this is a voice channel, otherwise we do nothing */ 
+			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
+				continue;
+			}
 
-		/* confirm this is a voice channel, otherwise we do nothing */ 
-		if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
-			continue;
+			/* extract the channel in question */
+			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+				ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n");
+				continue;
+			}
+			if (ftdm_map_test_bit(lockmap, bn)) {
+				/* unlock the channel */
+				ftdm_channel_unlock(ftdmchan);
+				ftdm_map_clear_bit(lockmap, bn);
+			}
 		}
 
-		/* extract the channel in question */
-		if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-			SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
-			continue;
-		}
+		ftdm_safe_free(lockmap);
 
-		/* unlock the channel */
-		ftdm_mutex_unlock(ftdmchan->mutex);
+		ftdm_channel_unlock(fchan);
 	}
 
+	ftdm_iterator_free(iter);
+
 	return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
 {
-	ftdm_channel_t 		*ftdmchan = NULL;
-	sngss7_chan_data_t  *sngss7_info = NULL;
-	sngss7_span_data_t	*sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
-	int 				i;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	int i = 0;
 
-	SS7_INFO("Rx GRA (%d:%d)\n", 
-				g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic, 
-				(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic + sngss7_span->rx_gra.range));
+	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
 
-	for (i = sngss7_span->rx_gra.circuit; i < (sngss7_span->rx_gra.circuit + sngss7_span->rx_gra.range + 1); i++) {
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
+		ftdm_channel_lock(fchan);
+
+		cinfo = fchan->call_data;
+
+		if (!cinfo->rx_gra.range) {
+
+			ftdm_channel_unlock(fchan);
 
-		/* extract the channel in question */
-		if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-			SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 			continue;
 		}
 
-		/* check if the channel is already procoessing the GRA */
-		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
-			/* move along */
-			continue;
-		}
+		SS7_INFO("Rx GRA (%d:%d)\n", 
+				g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic, 
+				(g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic + cinfo->rx_gra.range));
 
-		/* lock the channel */
-		ftdm_mutex_lock(ftdmchan->mutex);
+		for (i = cinfo->rx_gra.circuit; i < (cinfo->rx_gra.circuit + cinfo->rx_gra.range + 1); i++) {
 
-		/* clear up any pending state changes */
-		while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-			ftdm_sangoma_ss7_process_state_change (ftdmchan);
-		}
+			/* confirm this is a voice channel, otherwise we do nothing */ 
+			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
+				continue;
+			} 
 
-
-
-		switch (ftdmchan->state) {
-		/**********************************************************************/
-		case FTDM_CHANNEL_STATE_RESTART:
-			
-			/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
-
-			/* go to DOWN */
-			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
-			break;
-		/**********************************************************************/
-		case FTDM_CHANNEL_STATE_DOWN:
-
-			/* do nothing, just drop the message */
-			SS7_DEBUG("Receveived GRA in down state, dropping\n");
-
-			break;
-		/**********************************************************************/
-		case FTDM_CHANNEL_STATE_TERMINATING:
-		case FTDM_CHANNEL_STATE_HANGUP:
-		case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-			
-			/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
-
-			break;
-		/**********************************************************************/
-		default:
-			/* ITU Q764-2.9.5.1.c -> release the circuit */
-			if (sngss7_span->rx_gra.cause != 0) {
-				ftdmchan->caller_data.hangup_cause = sngss7_span->rx_gra.cause;
-			} else {
-				ftdmchan->caller_data.hangup_cause = 98;	/* Message not compatiable with call state */
+			/* extract the channel in question */
+			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+				continue;
 			}
 
-			/* go to terminating to hang up the call */
-			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-			break;
-		/**********************************************************************/
+			/* check if the channel is already processing the GRA */
+			if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
+				/* move along */
+				continue;
+			}
+
+			/* lock the channel */
+			ftdm_channel_lock(ftdmchan);
+
+			/* clear up any pending state changes */
+			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+				ftdm_sangoma_ss7_process_state_change (ftdmchan);
+			}
+
+			switch (ftdmchan->state) {
+			/**********************************************************************/
+			case FTDM_CHANNEL_STATE_RESTART:
+				
+				/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+
+				/* go to DOWN */
+				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+				break;
+			/**********************************************************************/
+			case FTDM_CHANNEL_STATE_DOWN:
+
+				/* do nothing, just drop the message */
+				SS7_DEBUG("Receveived GRA in down state, dropping\n");
+
+				break;
+			/**********************************************************************/
+			case FTDM_CHANNEL_STATE_TERMINATING:
+			case FTDM_CHANNEL_STATE_HANGUP:
+			case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+				
+				/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+
+				break;
+			/**********************************************************************/
+			default:
+				/* ITU Q764-2.9.5.1.c -> release the circuit */
+				if (cinfo->rx_gra.cause != 0) {
+					ftdmchan->caller_data.hangup_cause = cinfo->rx_gra.cause;
+				} else {
+					ftdmchan->caller_data.hangup_cause = 98;	/* Message not compatiable with call state */
+				}
+
+				/* go to terminating to hang up the call */
+				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+				break;
+			/**********************************************************************/
+			}
+
+			ftdm_channel_unlock(ftdmchan);
 		}
 
-		/* unlock the channel again before we exit */
-		ftdm_mutex_unlock(ftdmchan->mutex);
-
-	} /* for ( circuits in request */
+		ftdm_channel_unlock(fchan);
+	}
 
+	ftdm_iterator_free(iter);
 
 	return FTDM_SUCCESS;
 }
@@ -1286,41 +1321,66 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
 /******************************************************************************/
 ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan)
 {
-	ftdm_channel_t 		*ftdmchan = NULL;
-	sngss7_chan_data_t  *sngss7_info = NULL;
-	sngss7_span_data_t	*sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
-	int 				i;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	ftdm_channel_t *ftdmchan = NULL;
+	sngss7_chan_data_t *sngss7_info = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
+	int i = 0;
 
-	for (i = sngss7_span->ucic.circuit; i < (sngss7_span->ucic.circuit + sngss7_span->ucic.range + 1); i++) {
+	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
+	curr = iter;
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
+
+		ftdm_channel_lock(fchan);
+
+		cinfo = fchan->call_data;
+
+		if (!cinfo->ucic.range) {
+
+			ftdm_channel_unlock(fchan);
 
-		/* extract the channel in question */
-		if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-			SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 			continue;
 		}
 
-		/* lock the channel */
-		ftdm_mutex_lock(ftdmchan->mutex);
+		for (i = cinfo->ucic.circuit; i < (cinfo->ucic.circuit + cinfo->ucic.range + 1); i++) {
 
-		SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UCIC\n", sngss7_info->circuit->cic);
+			/* extract the channel in question */
+			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+				continue;
+			}
 
-		/* clear up any pending state changes */
-		while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-			ftdm_sangoma_ss7_process_state_change (ftdmchan);
+			/* lock the channel */
+			ftdm_channel_lock(ftdmchan);
+
+			SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx UCIC\n", sngss7_info->circuit->cic);
+
+			/* clear up any pending state changes */
+			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+				ftdm_sangoma_ss7_process_state_change (ftdmchan);
+			}
+
+			/* throw the ckt block flag */
+			sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
+
+			/* set the channel to suspended state */
+			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+
+			/* unlock the channel again before we exit */
+			ftdm_channel_unlock(ftdmchan);
 		}
+		/* clear out the ucic data since we're done with it */
+		memset(&cinfo->ucic, 0, sizeof(cinfo->ucic));
 
-		/* throw the ckt block flag */
-		sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
-
-		/* set the channel to suspended state */
-		ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
-
-		/* unlock the channel again before we exit */
-		ftdm_mutex_unlock(ftdmchan->mutex);
+		ftdm_channel_unlock(fchan);
 	}
 
-	/* clear out the ucic data since we're done with it */
-	memset(&sngss7_span->ucic, 0x0, sizeof(sngss7_group_data_t));
+	ftdm_clear_flag(sngss7_span, SNGSS7_UCIC_PENDING);
+
+	ftdm_iterator_free(iter);
 
 	return FTDM_SUCCESS;
 }
@@ -1339,11 +1399,36 @@ ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info)
 /******************************************************************************/
 ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info)
 {
-	ftdm_channel_t		*ftdmchan = sngss7_info->ftdmchan;
-	sngss7_span_data_t	*sngss7_span = ftdmchan->span->signal_data;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
+	sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmchan->span->signal_data;
 
-	/* clear the rx_grs data fields */
-	memset(&sngss7_span->rx_grs, 0x0, sizeof(sngss7_group_data_t));
+	memset(&sngss7_info->rx_grs, 0, sizeof(sngss7_info->rx_grs));
+
+	iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL);
+	curr = iter;
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
+
+		ftdm_channel_lock(fchan);
+
+		cinfo = fchan->call_data;
+		if (cinfo->rx_grs.range) {
+			/* there is still another grs pending, do not clear the SNGSS7_RX_GRS_PENDING flag yet */
+			ftdm_channel_unlock(fchan);
+			goto done;
+		}
+
+		ftdm_channel_unlock(fchan);
+	}
+
+	/* if we're here is because there is no other grs going on now in this span */
+	ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRS_PENDING);
+
+done:
+	ftdm_iterator_free(iter);
 
 	return FTDM_SUCCESS;
 }
@@ -1351,11 +1436,38 @@ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info)
 /******************************************************************************/
 ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info)
 {
-	ftdm_channel_t		*ftdmchan = sngss7_info->ftdmchan;
-	sngss7_span_data_t	*sngss7_span = ftdmchan->span->signal_data;
+	ftdm_iterator_t *iter = NULL;
+	ftdm_iterator_t *curr = NULL;
+	sngss7_chan_data_t *cinfo = NULL;
+	ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
+	sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
 
 	/* clear the rx_grs data fields */
-	memset(&sngss7_span->rx_gra, 0x0, sizeof(sngss7_group_data_t));
+	memset(&sngss7_info->rx_gra, 0, sizeof(sngss7_info->rx_gra));
+
+	iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL);
+	curr = iter;
+	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
+		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
+
+		ftdm_channel_lock(fchan);
+
+		cinfo = fchan->call_data;
+		if (cinfo->rx_gra.range) {
+			/* there is still another gra pending, do not clear the SNGSS7_RX_GRA_PENDING flag yet */
+			ftdm_channel_unlock(fchan);
+			goto done;
+		}
+
+		ftdm_channel_unlock(fchan);
+	}
+
+	/* if we're here is because there is no other gra pending in this span */
+	ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRA_PENDING);
+
+done:
+
+	ftdm_iterator_free(iter);
 
 	return FTDM_SUCCESS;
 }
@@ -1374,12 +1486,8 @@ ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info)
 /******************************************************************************/
 ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info)
 {
-	ftdm_channel_t		*ftdmchan = sngss7_info->ftdmchan;
-	sngss7_span_data_t	*sngss7_span = ftdmchan->span->signal_data;
-
-	/* clear the rx_grs data fields */
-	memset(&sngss7_span->tx_grs, 0x0, sizeof(sngss7_group_data_t));
-
+	/* clear everything up */
+	memset(&sngss7_info->tx_grs, 0, sizeof(sngss7_info->tx_grs));
 	return FTDM_SUCCESS;
 }
 
diff --git a/libs/freetdm/src/include/ftdm_threadmutex.h b/libs/freetdm/src/include/ftdm_threadmutex.h
index c5afb46eb5..2e802fe913 100644
--- a/libs/freetdm/src/include/ftdm_threadmutex.h
+++ b/libs/freetdm/src/include/ftdm_threadmutex.h
@@ -43,14 +43,14 @@ FT_DECLARE(void) ftdm_thread_override_default_stacksize(ftdm_size_t size);
 FT_DECLARE(ftdm_status_t) ftdm_mutex_create(ftdm_mutex_t **mutex);
 FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex);
 
-#define ftdm_mutex_lock(_x) _ftdm_mutex_lock(_x)
-FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(ftdm_mutex_t *mutex);
+#define ftdm_mutex_lock(_x) _ftdm_mutex_lock(__FILE__, __LINE__, __FUNCTION__, _x)
+FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex);
 
-#define ftdm_mutex_trylock(_x) _ftdm_mutex_trylock(_x)
-FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(ftdm_mutex_t *mutex);
+#define ftdm_mutex_trylock(_x) _ftdm_mutex_trylock(__FILE__, __LINE__, __FUNCTION__, _x)
+FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex);
 
-#define ftdm_mutex_unlock(_x) _ftdm_mutex_unlock(_x)
-FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(ftdm_mutex_t *mutex);
+#define ftdm_mutex_unlock(_x) _ftdm_mutex_unlock(__FILE__, __LINE__, __FUNCTION__, _x)
+FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex);
 
 FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **cond, ftdm_socket_t device);
 FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **cond);
diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h
index 67015c6fdf..e4be27ce40 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -719,8 +719,8 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *
 */
 #define ftdm_socket_close(it) if (it > -1) { close(it); it = -1;}
 
-#define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex)
-#define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex)
+#define ftdm_channel_lock(chan) ftdm_mutex_lock((chan)->mutex)
+#define ftdm_channel_unlock(chan) ftdm_mutex_unlock((chan)->mutex)
 
 #define ftdm_log_throttle(level, ...) \
 	time_current_throttle_log = ftdm_current_time_in_ms(); \
@@ -777,6 +777,13 @@ static __inline__ int16_t ftdm_saturated_add(int16_t sample1, int16_t sample2)
 	return (int16_t)addres;
 }
 
+/* Bitmap helper functions */
+typedef long ftdm_bitmap_t;
+#define FTDM_BITMAP_NBITS (sizeof(ftdm_bitmap_t) * 8)
+#define ftdm_map_set_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] |= ((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS)))
+#define ftdm_map_clear_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] &= ~((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS)))
+#define ftdm_map_test_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] & ((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS)))
+
 #ifdef __cplusplus
 }
 #endif