Browse Source

qcacld-3.0: Store NDP connection info in NAN's peer objects

To support NAN Datapath concurrencies driver needs to be aware
of the primary NDP connection for each NDI. If the primary
NDP has ended, driver needs to update NDI with the second NDP
if it exists. For this purpose driver needs to track the NDP
connections for every peer associated with NDI. Store and
update the primary NDP connection info in peer object for
NDP confirm, NDP End & NDP schedule update.

Store and update NDP connection info in NAN's peer objects.

Change-Id: I7d2c8c513beceebf155596bfa73841a834d9a97a
CRs-Fixed: 2406402
Nachiket Kukade 6 years ago
parent
commit
6f46abc449
2 changed files with 173 additions and 3 deletions
  1. 169 3
      components/nan/core/src/nan_main.c
  2. 4 0
      components/nan/core/src/nan_main_i.h

+ 169 - 3
components/nan/core/src/nan_main.c

@@ -292,8 +292,10 @@ QDF_STATUS nan_scheduled_msg_handler(struct scheduler_msg *msg)
 	return QDF_STATUS_SUCCESS;
 }
 
-static QDF_STATUS nan_increment_ndp_sessions(struct wlan_objmgr_psoc *psoc,
-					     struct qdf_mac_addr *peer_ndi_mac)
+static QDF_STATUS
+nan_increment_ndp_sessions(struct wlan_objmgr_psoc *psoc,
+			   struct qdf_mac_addr *peer_ndi_mac,
+			   struct nan_datapath_channel_info *ndp_chan_info)
 {
 	struct wlan_objmgr_peer *peer;
 	struct nan_peer_priv_obj *peer_nan_obj;
@@ -322,6 +324,12 @@ static QDF_STATUS nan_increment_ndp_sessions(struct wlan_objmgr_psoc *psoc,
 		wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID);
 		return QDF_STATUS_E_FAILURE;
 	}
+	/*
+	 * Store the first channel info in NDP Confirm as the home channel info
+	 * and store it in the peer private object.
+	 */
+	qdf_mem_copy(&peer_nan_obj->home_chan_info, ndp_chan_info,
+		     sizeof(struct nan_datapath_channel_info));
 	peer_nan_obj->active_ndp_sessions++;
 	qdf_spin_unlock_bh(&peer_nan_obj->lock);
 	wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID);
@@ -365,12 +373,115 @@ static QDF_STATUS nan_decrement_ndp_sessions(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+static QDF_STATUS
+ndi_remove_and_update_primary_connection(struct wlan_objmgr_psoc *psoc,
+					 struct wlan_objmgr_vdev *vdev)
+{
+	struct nan_vdev_priv_obj *vdev_nan_obj;
+	struct nan_psoc_priv_obj *psoc_nan_obj;
+	struct nan_peer_priv_obj *peer_nan_obj = NULL;
+	struct wlan_objmgr_peer *peer, *peer_next;
+	qdf_list_t *peer_list;
+
+	psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
+	vdev_nan_obj = nan_get_vdev_priv_obj(vdev);
+
+	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
+	if (!peer_list) {
+		nan_err("Peer list for vdev obj is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list,
+						    WLAN_NAN_ID);
+
+	while (peer) {
+		peer_nan_obj = nan_get_peer_priv_obj(peer);
+		if (!peer_nan_obj)
+			nan_err("NAN peer object for Peer " QDF_MAC_ADDR_STR " is NULL",
+				QDF_MAC_ADDR_ARRAY(wlan_peer_get_macaddr(peer)));
+		else if (peer_nan_obj->active_ndp_sessions)
+			break;
+
+		peer_next = wlan_peer_get_next_active_peer_of_vdev(vdev,
+								   peer_list,
+								   peer,
+								   WLAN_NAN_ID);
+		wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID);
+		peer = peer_next;
+	}
+
+	if (!peer && psoc_nan_obj->nan_caps.ndi_dbs_supported) {
+		/* TODO: Remove connection from policy manager tables */
+		return QDF_STATUS_SUCCESS;
+	}
+
+	if (peer_nan_obj && psoc_nan_obj->nan_caps.ndi_dbs_supported) {
+		/* TODO: Update NDI's primary chan info to WMA */
+		/* TODO: Update policy mgr with connection info */
+		qdf_mem_copy(vdev_nan_obj->primary_peer_mac.bytes,
+			     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
+	}
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID);
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS
+ndi_update_ndp_session(struct wlan_objmgr_vdev *vdev,
+		       struct qdf_mac_addr *peer_ndi_mac,
+		       struct nan_datapath_channel_info *ndp_chan_info)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_peer *peer;
+	struct nan_vdev_priv_obj *vdev_nan_obj;
+	struct nan_peer_priv_obj *peer_nan_obj;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+
+	vdev_nan_obj = nan_get_vdev_priv_obj(vdev);
+	if (!vdev_nan_obj) {
+		nan_err("NAN vdev private object is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	peer = wlan_objmgr_get_peer_by_mac(psoc,
+					   peer_ndi_mac->bytes,
+					   WLAN_NAN_ID);
+
+	if (!peer) {
+		nan_err("peer object is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	peer_nan_obj = nan_get_peer_priv_obj(peer);
+	if (!peer_nan_obj) {
+		nan_err("peer_nan_obj is null");
+		wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	qdf_spin_lock_bh(&peer_nan_obj->lock);
+	qdf_mem_copy(&peer_nan_obj->home_chan_info, ndp_chan_info,
+		     sizeof(*ndp_chan_info));
+	/* TODO: Update NDI's primary chan info to WMA */
+	qdf_spin_unlock_bh(&peer_nan_obj->lock);
+	wlan_objmgr_peer_release_ref(peer, WLAN_NAN_ID);
+
+	if (qdf_is_macaddr_equal(&vdev_nan_obj->primary_peer_mac,
+				 peer_ndi_mac)) {
+		/* TODO: Update policy mgr with connection info */
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
 static QDF_STATUS nan_handle_confirm(
 				struct nan_datapath_confirm_event *confirm)
 {
 	uint8_t vdev_id;
 	struct wlan_objmgr_psoc *psoc;
 	struct nan_psoc_priv_obj *psoc_nan_obj;
+	struct nan_vdev_priv_obj *vdev_nan_obj;
 
 	vdev_id = wlan_vdev_get_id(confirm->vdev);
 	psoc = wlan_vdev_get_psoc(confirm->vdev);
@@ -385,6 +496,12 @@ static QDF_STATUS nan_handle_confirm(
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	vdev_nan_obj = nan_get_vdev_priv_obj(confirm->vdev);
+	if (!vdev_nan_obj) {
+		nan_err("vdev_nan_obj is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
 	if (confirm->rsp_code != NAN_DATAPATH_RESPONSE_ACCEPT &&
 	    confirm->num_active_ndps_on_peer == 0) {
 		/*
@@ -400,11 +517,33 @@ static QDF_STATUS nan_handle_confirm(
 
 	/* Increment NDP sessions for the Peer */
 	if (confirm->rsp_code == NAN_DATAPATH_RESPONSE_ACCEPT)
-		nan_increment_ndp_sessions(psoc, &confirm->peer_ndi_mac_addr);
+		nan_increment_ndp_sessions(psoc, &confirm->peer_ndi_mac_addr,
+					   &confirm->ch[0]);
 
 	psoc_nan_obj->cb_obj.os_if_ndp_event_handler(psoc, confirm->vdev,
 						     NDP_CONFIRM, confirm);
 
+	if (confirm->rsp_code == NAN_DATAPATH_RESPONSE_ACCEPT &&
+	    vdev_nan_obj->active_ndp_peers == 1) {
+		/*
+		 * If this is the NDI's first NDP, store the NDP instance in
+		 * vdev object as its primary connection. If this instance ends
+		 * the second NDP should take its place.
+		 */
+		qdf_mem_copy(vdev_nan_obj->primary_peer_mac.bytes,
+			     &confirm->peer_ndi_mac_addr, QDF_MAC_ADDR_SIZE);
+
+		/* TODO: Update primary connection info in the WMA interfaces */
+
+		if (psoc_nan_obj->nan_caps.ndi_dbs_supported) {
+			/*
+			* TODO: Update connection in Policy Manager if NDI
+			* concurrencies are supported and this is the first
+			* active NDP for the NDI.
+			*/
+		}
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -547,6 +686,8 @@ static QDF_STATUS nan_handle_end_ind(
 	uint32_t i;
 	struct wlan_objmgr_psoc *psoc;
 	struct nan_psoc_priv_obj *psoc_nan_obj;
+	struct wlan_objmgr_vdev *vdev_itr;
+	struct nan_vdev_priv_obj *vdev_nan_obj;
 
 	psoc = wlan_vdev_get_psoc(ind->vdev);
 	if (!psoc) {
@@ -565,6 +706,30 @@ static QDF_STATUS nan_handle_end_ind(
 		nan_decrement_ndp_sessions(psoc,
 					   &ind->ndp_map[i].peer_ndi_mac_addr);
 
+	for (i = 0; i < ind->num_ndp_ids; i++) {
+		vdev_itr = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+							ind->ndp_map[i].vdev_id,
+							WLAN_NAN_ID);
+		if (!vdev_itr) {
+			nan_err("NAN vdev object is NULL");
+			continue;
+		}
+
+		vdev_nan_obj = nan_get_vdev_priv_obj(vdev_itr);
+		if (!vdev_nan_obj) {
+			wlan_objmgr_vdev_release_ref(vdev_itr, WLAN_NAN_ID);
+			nan_err("NAN vdev private object is NULL");
+			continue;
+		}
+
+		if (qdf_is_macaddr_equal(&vdev_nan_obj->primary_peer_mac,
+					 &ind->ndp_map[i].peer_ndi_mac_addr))
+			ndi_remove_and_update_primary_connection(psoc,
+								 vdev_itr);
+
+		wlan_objmgr_vdev_release_ref(vdev_itr, WLAN_NAN_ID);
+	}
+
 	psoc_nan_obj->cb_obj.ndp_delete_peers(ind->ndp_map, ind->num_ndp_ids);
 	psoc_nan_obj->cb_obj.os_if_ndp_event_handler(psoc, ind->vdev,
 						     NDP_END_IND, ind);
@@ -666,6 +831,7 @@ static QDF_STATUS nan_handle_schedule_update(
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	ndi_update_ndp_session(ind->vdev, &ind->peer_addr, &ind->ch[0]);
 	psoc_nan_obj->cb_obj.os_if_ndp_event_handler(psoc, ind->vdev,
 						     NDP_SCHEDULE_UPDATE, ind);
 

+ 4 - 0
components/nan/core/src/nan_main_i.h

@@ -125,6 +125,7 @@ struct nan_psoc_priv_obj {
  * @ndp_delete_transaction_id: transaction id for delete req
  * @ndi_delete_rsp_reason: reason code for ndi_delete rsp
  * @ndi_delete_rsp_status: status for ndi_delete rsp
+ * @primary_peer_mac: Primary NDP Peer mac address for the vdev
  */
 struct nan_vdev_priv_obj {
 	qdf_spinlock_t lock;
@@ -134,16 +135,19 @@ struct nan_vdev_priv_obj {
 	uint16_t ndp_delete_transaction_id;
 	uint32_t ndi_delete_rsp_reason;
 	uint32_t ndi_delete_rsp_status;
+	struct qdf_mac_addr primary_peer_mac;
 };
 
 /**
  * struct nan_peer_priv_obj - nan private peer obj
  * @lock: lock to be acquired before reading or writing to object
  * @active_ndp_sessions: number of active ndp sessions for this peer
+ * @home_chan_info: Home channel info for the NDP associated with the Peer
  */
 struct nan_peer_priv_obj {
 	qdf_spinlock_t lock;
 	uint32_t active_ndp_sessions;
+	struct nan_datapath_channel_info home_chan_info;
 };
 
 /**