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
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
#include "wlan_objmgr_psoc_obj.h"
|
#include "wlan_objmgr_psoc_obj.h"
|
||||||
#include "wlan_objmgr_pdev_obj.h"
|
#include "wlan_objmgr_pdev_obj.h"
|
||||||
#include "wlan_objmgr_vdev_obj.h"
|
#include "wlan_objmgr_vdev_obj.h"
|
||||||
|
#include "wlan_objmgr_peer_obj.h"
|
||||||
#include "wlan_utility.h"
|
#include "wlan_utility.h"
|
||||||
|
|
||||||
/* NLA policy */
|
/* NLA policy */
|
||||||
@@ -188,10 +189,20 @@ static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return cb_obj.ndi_start(iface_name, transaction_id);
|
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,
|
static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
|
||||||
struct nlattr **tb)
|
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]);
|
nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
|
||||||
vdev_id = wlan_vdev_get_id(nan_vdev);
|
vdev_id = wlan_vdev_get_id(nan_vdev);
|
||||||
num_peers = ucfg_nan_get_active_peers(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
|
* wlan_util_get_vdev_by_ifname increments ref count
|
||||||
* decrement here since vdev returned by that api is not used any more
|
* decrement here since vdev returned by that api is not used any more
|
||||||
|
@@ -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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -61,6 +61,43 @@ nan_psoc_notif_failed:
|
|||||||
return status;
|
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(
|
static QDF_STATUS nan_psoc_obj_destroyed_notification(
|
||||||
struct wlan_objmgr_psoc *psoc, void *arg_list)
|
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;
|
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,
|
status = wlan_objmgr_psoc_component_obj_detach(psoc,
|
||||||
WLAN_UMAC_COMP_NAN, nan_obj);
|
WLAN_UMAC_COMP_NAN, nan_obj);
|
||||||
if (QDF_IS_STATUS_ERROR(status))
|
if (QDF_IS_STATUS_ERROR(status))
|
||||||
|
Reference in New Issue
Block a user