Skip to content

Commit

Permalink
Merge branch 'stray_call' into 'master'
Browse files Browse the repository at this point in the history
Fix data connection dying after switching radio tech

See merge request mer-core/ofono!198
  • Loading branch information
Slava Monich committed Oct 26, 2018
2 parents cf99a57 + 9c529dc commit 9e6f772
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 5 deletions.
70 changes: 66 additions & 4 deletions ofono/drivers/ril/ril_data.c
Expand Up @@ -114,6 +114,7 @@ struct ril_data_priv {
guint query_id;
gulong io_event_id[IO_EVENT_COUNT];
gulong settings_event_id[SETTINGS_EVENT_COUNT];
GHashTable* grab;
};

enum ril_data_signal {
Expand Down Expand Up @@ -185,7 +186,7 @@ struct ril_data_request_allow_data {

static void ril_data_manager_check_data(struct ril_data_manager *dm);
static void ril_data_manager_check_network_mode(struct ril_data_manager *dm);

static void ril_data_call_deact_cid(struct ril_data *data, int cid);
static void ril_data_power_update(struct ril_data *self);
static void ril_data_signal_emit(struct ril_data *self, enum ril_data_signal id)
{
Expand Down Expand Up @@ -545,6 +546,10 @@ struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,
static void ril_data_set_calls(struct ril_data *self,
struct ril_data_call_list *list)
{
struct ril_data_priv *priv = self->priv;
GHashTableIter it;
gpointer key;

if (!ril_data_call_list_equal(self->data_calls, list)) {
DBG("data calls changed");
ril_data_call_list_free(self->data_calls);
Expand All @@ -553,6 +558,32 @@ static void ril_data_set_calls(struct ril_data *self,
} else {
ril_data_call_list_free(list);
}

/* Clean up the grab table */
g_hash_table_iter_init(&it, priv->grab);
while (g_hash_table_iter_next(&it, &key, NULL)) {
const int cid = GPOINTER_TO_INT(key);

if (!ril_data_call_find(self->data_calls, cid)) {
g_hash_table_iter_remove(&it);
}
}

if (self->data_calls) {
GSList *l;

/* Disconnect stray calls (one at a time) */
for (l = self->data_calls->calls; l; l = l->next) {
struct ril_data_call *dc = l->data;

key = GINT_TO_POINTER(dc->cid);
if (!g_hash_table_contains(priv->grab, key)) {
DBG_(self, "stray call %u", dc->cid);
ril_data_call_deact_cid(self, dc->cid);
break;
}
}
}
}

static void ril_data_check_allowed(struct ril_data *self, gboolean was_allowed)
Expand Down Expand Up @@ -1083,6 +1114,11 @@ static struct ril_data_request *ril_data_call_deact_new(struct ril_data *data,
return req;
}

static void ril_data_call_deact_cid(struct ril_data *data, int cid)
{
ril_data_request_queue(ril_data_call_deact_new(data, cid, NULL, NULL));
}

/*==========================================================================*
* ril_data_allow_request
*==========================================================================*/
Expand Down Expand Up @@ -1323,9 +1359,7 @@ static void ril_data_deactivate_all(struct ril_data *self)
struct ril_data_call *call = l->data;
if (call->status == PDP_FAIL_NONE) {
DBG_(self, "deactivating call %u", call->cid);
ril_data_request_queue(
ril_data_call_deact_new(self,
call->cid, NULL, NULL));
ril_data_call_deact_cid(self, call->cid);
}
}
}
Expand Down Expand Up @@ -1492,12 +1526,39 @@ struct ril_data_request *ril_data_call_deactivate(struct ril_data *self,
return req;
}

gboolean ril_data_call_grab(struct ril_data *self, int cid, void *cookie)
{
if (self && cookie && ril_data_call_find(self->data_calls, cid)) {
struct ril_data_priv *priv = self->priv;
gpointer key = GINT_TO_POINTER(cid);
void *prev = g_hash_table_lookup(priv->grab, key);

if (!prev) {
g_hash_table_insert(priv->grab, key, cookie);
return TRUE;
} else {
return (prev == cookie);
}
}
return FALSE;
}

void ril_data_call_release(struct ril_data *self, int cid, void *cookie)
{
if (self && cookie) {
struct ril_data_priv *priv = self->priv;

g_hash_table_remove(priv->grab, GUINT_TO_POINTER(cid));
}
}

static void ril_data_init(struct ril_data *self)
{
struct ril_data_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
RIL_DATA_TYPE, struct ril_data_priv);

self->priv = priv;
priv->grab = g_hash_table_new(g_direct_hash, g_direct_equal);
}

static void ril_data_dispose(GObject *object)
Expand Down Expand Up @@ -1525,6 +1586,7 @@ static void ril_data_dispose(GObject *object)

dm->data_list = g_slist_remove(dm->data_list, self);
ril_data_manager_check_data(dm);
g_hash_table_destroy(priv->grab);
G_OBJECT_CLASS(ril_data_parent_class)->dispose(object);
}

Expand Down
3 changes: 3 additions & 0 deletions ofono/drivers/ril/ril_data.h
Expand Up @@ -123,6 +123,9 @@ struct ril_data_request *ril_data_call_deactivate(struct ril_data *data,
void ril_data_request_detach(struct ril_data_request *req);
void ril_data_request_cancel(struct ril_data_request *req);

gboolean ril_data_call_grab(struct ril_data *data, int cid, void *cookie);
void ril_data_call_release(struct ril_data *data, int cid, void *cookie);

void ril_data_call_free(struct ril_data_call *call);
struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,
Expand Down
2 changes: 2 additions & 0 deletions ofono/drivers/ril/ril_gprs_context.c
Expand Up @@ -88,6 +88,7 @@ static int ril_gprs_context_address_family(const char *addr)
static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
{
if (gcd->active_call) {
ril_data_call_release(gcd->data, gcd->active_call->cid, gcd);
ril_data_call_free(gcd->active_call);
gcd->active_call = NULL;
}
Expand All @@ -111,6 +112,7 @@ static void ril_gprs_context_set_active_call(struct ril_gprs_context *gcd,
gcd->mtu_watch = mtu_watch_new(MAX_MTU);
}
mtu_watch_set_ifname(gcd->mtu_watch, call->ifname);
ril_data_call_grab(gcd->data, call->cid, gcd);
} else {
ril_gprs_context_free_active_call(gcd);
}
Expand Down
20 changes: 19 additions & 1 deletion ofono/drivers/ril/ril_radio_caps.c
Expand Up @@ -1284,6 +1284,24 @@ static GSList *ril_radio_caps_manager_empty_slots
return found;
}

static guint ril_radio_caps_manager_sim_count
(struct ril_radio_caps_manager *self)
{
const GPtrArray *list = self->caps_list;
guint i, count = 0;

for (i = 0; i < list->len; i++) {
const struct ril_radio_caps *caps = list->pdata[i];

if (caps->simcard->status->card_state ==
RIL_CARDSTATE_PRESENT) {
count++;
}
}

return count;
}

/**
* There could be no capability mismatch but LTE could be enabled for
* the slot that has no SIM card in it. That's a waste, fix it.
Expand Down Expand Up @@ -1327,7 +1345,7 @@ static void ril_radio_caps_manager_check(struct ril_radio_caps_manager *self)
if (ril_radio_caps_manager_can_check(self)) {
const int first = ril_radio_caps_manager_first_mismatch(self);

if (first >= 0) {
if (first >= 0 && ril_radio_caps_manager_sim_count(self) > 1) {
if (ril_radio_caps_manager_update_caps(self, first)) {
ril_radio_caps_manager_start_transaction(self);
}
Expand Down

0 comments on commit 9e6f772

Please sign in to comment.