lchan: Handle the abnormal case of channel getting closed
The abnormal case is that lchan_free ist getting called due a RSL_MT_CHAN_REL_ACK in the RSL but the refcount of this channel is not zero. This means that some "logical operation" is still going on that needs to be cancelled. Instead of always queuing up all operations in the struct gsm_lchan use the signal framework to inform higher layers about this abnormal case. In gsm_04_08.c a signal handler is installed and in the abnormal case the location updating request operation is freed.
This commit is contained in:
parent
c7b86f9011
commit
7c19f74084
|
@ -37,6 +37,7 @@ enum signal_subsystems {
|
|||
SS_SMS,
|
||||
SS_ABISIP,
|
||||
SS_NM,
|
||||
SS_LCHAN,
|
||||
};
|
||||
|
||||
/* SS_PAGING signals */
|
||||
|
@ -55,6 +56,16 @@ enum signal_nm {
|
|||
S_NM_FAIL_REP, /* GSM 12.21 failure event report */
|
||||
};
|
||||
|
||||
/* SS_LCHAN signals */
|
||||
enum signal_lchan {
|
||||
/*
|
||||
* The lchan got freed with an use_count != 0 and error
|
||||
* recovery needs to be carried out from within the
|
||||
* signal handler.
|
||||
*/
|
||||
S_LCHAN_UNEXPECTED_RELEASE,
|
||||
};
|
||||
|
||||
typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <openbsc/abis_nm.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
static void auto_release_channel(void *_lchan);
|
||||
|
||||
|
@ -193,8 +194,9 @@ void lchan_free(struct gsm_lchan *lchan)
|
|||
lchan->subscr = 0;
|
||||
}
|
||||
|
||||
/* We might kill an active channel... FIXME: call cancellations */
|
||||
/* We might kill an active channel... */
|
||||
if (lchan->use_count != 0) {
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan);
|
||||
lchan->use_count = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -182,6 +182,31 @@ static void allocate_loc_updating_req(struct gsm_lchan *lchan)
|
|||
memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
|
||||
}
|
||||
|
||||
static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Cancel any outstanding location updating request
|
||||
* operation taking place on the lchan.
|
||||
*/
|
||||
struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data;
|
||||
release_loc_updating_req(lchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will be ran by the linker when loading the DSO. We use it to
|
||||
* do system initialization, e.g. registration of signal handlers.
|
||||
*/
|
||||
static __attribute__((constructor)) void on_dso_load_0408(void)
|
||||
{
|
||||
register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
|
||||
}
|
||||
|
||||
static void to_bcd(u_int8_t *bcd, u_int16_t val)
|
||||
{
|
||||
bcd[2] = val % 10;
|
||||
|
|
Loading…
Reference in New Issue