Merge branch 'zecke/changes/paging-order'

Various paging clean-ups. I couldn't re-produce the assert that
was hit by Rhizomatica in the subscriber code. Let's clean things
up a bit to avoid some of the potential issues this code had.

Always stop paging regardless of where the subscriber is at the
time of the cancellation.
diff --git a/openbsc/src/libbsc/paging.c b/openbsc/src/libbsc/paging.c
index 8bc10e6..9ae28e0 100644
--- a/openbsc/src/libbsc/paging.c
+++ b/openbsc/src/libbsc/paging.c
@@ -341,8 +341,10 @@
 			break;
 
 		rc = paging_request_bts(bts, subscr, type, cbfn, data);
-		if (rc < 0)
+		if (rc < 0) {
+			paging_request_stop(NULL, subscr, NULL, NULL);
 			return rc;
+		}
 		num_pages += rc;
 	} while (1);
 
@@ -389,28 +391,21 @@
 			 struct gsm_subscriber_connection *conn,
 			 struct msgb *msg)
 {
-	struct gsm_bts *bts = NULL;
+	struct gsm_bts *bts;
 
 	log_set_context(BSC_CTX_SUBSCR, subscr);
 
+	/* Stop this first and dispatch the request */
 	if (_bts)
 		_paging_request_stop(_bts, subscr, conn, msg);
 
-	do {
-		/*
-		 * FIXME: Don't use the lac of the subscriber...
-		 * as it might have magically changed the lac.. use the
-		 * location area of the _bts as reconfiguration of the
-		 * network is probably happening less often.
-		 */
-		bts = gsm_bts_by_lac(subscr->group->net, subscr->lac, bts);
-		if (!bts)
-			break;
-
-		/* Stop paging */
-		if (bts != _bts)
-			_paging_request_stop(bts, subscr, NULL, NULL);
-	} while (1);
+	/* Make sure to cancel this everywhere else */
+	llist_for_each_entry(bts, &subscr->group->net->bts_list, list) {
+		/* Sort of an optimization. */
+		if (bts == _bts)
+			continue;
+		_paging_request_stop(bts, subscr, NULL, NULL);
+	}
 }
 
 void paging_update_buffer_space(struct gsm_bts *bts, uint16_t free_slots)
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index 4559de5..442e84c 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -84,6 +84,14 @@
 
 	OSMO_ASSERT(subscr->is_paging);
 
+	/*
+	 * Stop paging on all other BTS. E.g. if this is
+	 * the first timeout on a BTS then the others will
+	 * timeout soon as well. Let's just stop everything
+	 * and forget we wanted to page.
+	 */
+	paging_request_stop(NULL, subscr, NULL, NULL);
+
 	/* Inform parts of the system we don't know */
 	sig_data.subscr = subscr;
 	sig_data.bts	= conn ? conn->bts : NULL;
@@ -96,15 +104,6 @@
 		&sig_data
 	);
 
-	/*
-	 * Stop paging on all other BTS. E.g. if this is
-	 * the first timeout on a BTS then the others will
-	 * timeout soon as well. Let's just stop everything
-	 * and forget we wanted to page.
-	 */
-	paging_request_stop(NULL, subscr, NULL, NULL);
-	subscr->is_paging = 0;
-
 	llist_for_each_entry_safe(request, tmp, &subscr->requests, entry) {
 		llist_del(&request->entry);
 		request->cbfn(hooknum, event, msg, data, request->param);
@@ -112,6 +111,7 @@
 	}
 
 	/* balanced with the moment we start paging */
+	subscr->is_paging = 0;
 	subscr_put(subscr);
 	return 0;
 }
diff --git a/openbsc/src/libmsc/silent_call.c b/openbsc/src/libmsc/silent_call.c
index 010c2b4..e9ece18 100644
--- a/openbsc/src/libmsc/silent_call.c
+++ b/openbsc/src/libmsc/silent_call.c
@@ -118,11 +118,10 @@
 /* initiate a silent call with a given subscriber */
 int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data, int type)
 {
-	int rc;
+	struct subscr_request *req;
 
-	rc = paging_request(subscr->group->net, subscr, type,
-			    paging_cb_silent, data);
-	return rc;
+	req = subscr_request_channel(subscr, type, paging_cb_silent, data);
+	return req != NULL;
 }
 
 /* end a silent call with a given subscriber */