bsc: Allow to page a BTS that is excluded from the RF lock

The RF lock excluded BTS was not paged at all. Now forward the
paging message to the handler and call a function that will check
if this LAC can be paged right now. Introduce a new paging method
that allows to page on a dedicated bts, refactor the code to use
this method for paging.
diff --git a/openbsc/include/openbsc/osmo_bsc_grace.h b/openbsc/include/openbsc/osmo_bsc_grace.h
index 4884996..e9c1a0a 100644
--- a/openbsc/include/openbsc/osmo_bsc_grace.h
+++ b/openbsc/include/openbsc/osmo_bsc_grace.h
@@ -1,6 +1,6 @@
 /*
- * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2012 by On-Waves
+ * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2013 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,9 @@
 
 #include "gsm_data.h"
 
+struct osmo_msc_data;
+
 int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts);
+int bsc_grace_paging_request(struct gsm_subscriber *sub, int type, struct osmo_msc_data *msc);
 
 #endif
diff --git a/openbsc/include/openbsc/paging.h b/openbsc/include/openbsc/paging.h
index e1438ba..2a10f4e 100644
--- a/openbsc/include/openbsc/paging.h
+++ b/openbsc/include/openbsc/paging.h
@@ -56,6 +56,8 @@
 /* schedule paging request */
 int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
 		   int type, gsm_cbfn *cbfn, void *data);
+int paging_request_bts(struct gsm_bts *bts, struct gsm_subscriber *subscr,
+		int type, gsm_cbfn *cbfn, void *data);
 
 /* stop paging requests */
 void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
diff --git a/openbsc/src/libbsc/paging.c b/openbsc/src/libbsc/paging.c
index b731dbc..286c57b 100644
--- a/openbsc/src/libbsc/paging.c
+++ b/openbsc/src/libbsc/paging.c
@@ -1,5 +1,5 @@
 /* Paging helper and manager.... */
-/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+/* (C) 2009,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -298,6 +298,26 @@
 	return 0;
 }
 
+int paging_request_bts(struct gsm_bts *bts, struct gsm_subscriber *subscr,
+		int type, gsm_cbfn *cbfn, void *data)
+{
+	int rc;
+
+	/* skip all currently inactive TRX */
+	if (!trx_is_usable(bts->c0))
+		return 0;
+
+	/* maybe it is the first time we use it */
+	paging_init_if_needed(bts);
+
+
+	/* Trigger paging, pass any error to the caller */
+	rc = _paging_request(bts, subscr, type, cbfn, data);
+	if (rc < 0)
+		return rc;
+	return 1;
+}
+
 int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
 		   int type, gsm_cbfn *cbfn, void *data)
 {
@@ -314,19 +334,10 @@
 		if (!bts)
 			break;
 
-		/* skip all currently inactive TRX */
-		if (!trx_is_usable(bts->c0))
-			continue;
-
-		/* maybe it is the first time we use it */
-		paging_init_if_needed(bts);
-
-		num_pages++;
-
-		/* Trigger paging, pass any error to caller */
-		rc = _paging_request(bts, subscr, type, cbfn, data);
+		rc = paging_request_bts(bts, subscr, type, cbfn, data);
 		if (rc < 0)
 			return rc;
+		num_pages += rc;
 	} while (1);
 
 	if (num_pages == 0)
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
index 8ea5a65..c2c2417 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
@@ -177,7 +177,7 @@
 	subscr->tmsi = tmsi;
 
 	LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac);
-	paging_request(msc->network, subscr, chan_needed, NULL, msc);
+	bsc_grace_paging_request(subscr, chan_needed, msc);
 	return 0;
 }
 
@@ -413,8 +413,7 @@
 		ret = bssmap_handle_reset_ack(msc, msg, length);
 		break;
 	case BSS_MAP_MSG_PAGING:
-		if (bsc_grace_allow_new_connection(msc->network, NULL))
-			ret = bssmap_handle_paging(msc, msg, length);
+		ret = bssmap_handle_paging(msc, msg, length);
 		break;
 	}
 
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_grace.c b/openbsc/src/osmo-bsc/osmo_bsc_grace.c
index ad0a37e..341971e 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_grace.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_grace.c
@@ -1,6 +1,6 @@
 /*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2013 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,17 +22,59 @@
 #include <openbsc/osmo_bsc_rf.h>
 #include <openbsc/osmo_msc_data.h>
 #include <openbsc/gsm_04_80.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/paging.h>
 #include <openbsc/signal.h>
 
 int bsc_grace_allow_new_connection(struct gsm_network *network, struct gsm_bts *bts)
 {
 	if (!network->bsc_data->rf_ctrl)
 		return 1;
-	if (bts && bts->excl_from_rf_lock)
+	if (bts->excl_from_rf_lock)
 		return 1;
 	return network->bsc_data->rf_ctrl->policy == S_RF_ON;
 }
 
+/**
+ * Try to not page if everything the cell is not on.
+ */
+int bsc_grace_paging_request(struct gsm_subscriber *subscr, int chan_needed,
+				struct osmo_msc_data *msc)
+{
+	struct gsm_bts *bts = NULL;
+
+	if (!subscr->net->bsc_data->rf_ctrl)
+		goto page;
+	if (subscr->net->bsc_data->rf_ctrl->policy == S_RF_ON)
+		goto page;
+
+	/*
+	 * Check if there is any BTS that is on for the given lac. Start
+	 * with NULL and iterate through all bts.
+	 */
+	do {
+		bts = gsm_bts_by_lac(subscr->net, subscr->lac, bts);
+		if (!bts)
+			break;
+
+		/*
+		 * continue if the BTS is not excluded from the lock
+		 */
+		if (!bts->excl_from_rf_lock)
+			continue;
+
+		/*
+		 * now page on this bts
+		 */
+		paging_request_bts(bts, subscr, chan_needed, NULL, msc);
+	} while (1);
+
+	/* All bts are either off or in the grace period */
+	return 0;
+page:
+	return paging_request(subscr->net, subscr, chan_needed, NULL, msc);
+}
+
 static int handle_sub(struct gsm_lchan *lchan, const char *text)
 {
 	struct gsm_subscriber_connection *conn;