Explorar el Código

qcacmn: Free NDI peers/vdev at time of ndi_delete/driver unload

Sometime user may not delete active NDP sessions before deleting NDI or
may not delete NDI before driver unload. In such case vdev/peer object
memory will leak. Free all NDI peers for that vdev before processing NDI
delete and free all NDI peers/vdev at driver unload.

Change-Id: I04631ffd611d6ded318ddfb65b2dfeba479c9bdc
CRs-Fixed: 2262769
Naveen Rawat hace 6 años
padre
commit
1e8e057a77
Se han modificado 2 ficheros con 64 adiciones y 2 borrados
  1. 18 1
      os_if/linux/nan/src/os_if_nan.c
  2. 46 1
      umac/nan/core/src/nan_api.c

+ 18 - 1
os_if/linux/nan/src/os_if_nan.c

@@ -33,6 +33,7 @@
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
+#include "wlan_objmgr_peer_obj.h"
 #include "wlan_utility.h"
 
 /* NLA policy */
@@ -188,10 +189,20 @@ static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
 		return ret;
 	}
 
-
 	return cb_obj.ndi_start(iface_name, transaction_id);
 }
 
+static void os_if_nan_vdev_delete_peer(struct wlan_objmgr_psoc *psoc,
+				       void *peer, void *nan_vdev)
+{
+	/* if peer belongs to nan vdev */
+	if (nan_vdev == wlan_peer_get_vdev(peer)) {
+		cfg80211_debug("deleting peer: %pM",
+			       wlan_peer_get_macaddr(peer));
+		wlan_objmgr_peer_obj_delete(peer);
+	}
+}
+
 static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
 					struct nlattr **tb)
 {
@@ -225,6 +236,12 @@ static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
 		nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
 	vdev_id = wlan_vdev_get_id(nan_vdev);
 	num_peers = ucfg_nan_get_active_peers(nan_vdev);
+
+	/* delete all peer for this interface first */
+	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
+				     os_if_nan_vdev_delete_peer,
+				     nan_vdev, 1, WLAN_UMAC_COMP_NAN);
+
 	/*
 	 * wlan_util_get_vdev_by_ifname increments ref count
 	 * decrement here since vdev returned by that api is not used any more

+ 46 - 1
umac/nan/core/src/nan_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -61,6 +61,43 @@ nan_psoc_notif_failed:
 	return status;
 }
 
+static void nan_psoc_delete_peer(struct wlan_objmgr_psoc *psoc,
+				 void *peer, void *arg)
+{
+	if (WLAN_PEER_NDP == wlan_peer_get_peer_type(peer))
+		wlan_objmgr_peer_obj_delete(peer);
+}
+
+static void nan_psoc_delete_vdev(struct wlan_objmgr_psoc *psoc,
+				 void *vdev, void *arg)
+{
+	enum nan_datapath_state state;
+	struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev);
+
+	if (!priv_obj) {
+		nan_err("priv_obj is null");
+		return;
+	}
+	/*
+	 * user may issue rrmod wlan without explicitly NDI Delete.
+	 * In that case pending NDI vdev state will not be DELETED/DELETEING
+	 * Forcefully delete vdev object
+	 */
+	if (QDF_NDI_MODE != wlan_vdev_mlme_get_opmode(vdev))
+		return;
+
+	qdf_spin_lock_bh(&priv_obj->lock);
+	state = priv_obj->state;
+	qdf_spin_unlock_bh(&priv_obj->lock);
+
+	/* if already in deleted or deleting state - do not delete */
+	if (state == NAN_DATA_NDI_DELETED_STATE ||
+	    state == NAN_DATA_NDI_DELETING_STATE)
+		return;
+
+	wlan_objmgr_vdev_obj_delete(vdev);
+}
+
 static QDF_STATUS nan_psoc_obj_destroyed_notification(
 				struct wlan_objmgr_psoc *psoc, void *arg_list)
 {
@@ -73,6 +110,14 @@ static QDF_STATUS nan_psoc_obj_destroyed_notification(
 		return QDF_STATUS_E_FAULT;
 	}
 
+	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
+				     nan_psoc_delete_peer,
+				     NULL, 1, WLAN_UMAC_COMP_NAN);
+
+	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
+				     nan_psoc_delete_vdev,
+				     NULL, 1, WLAN_UMAC_COMP_NAN);
+
 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
 					WLAN_UMAC_COMP_NAN, nan_obj);
 	if (QDF_IS_STATUS_ERROR(status))