diff --git a/os_if/linux/nan/src/os_if_nan.c b/os_if/linux/nan/src/os_if_nan.c index 95ab8154df7f..614bf2febbc8 100644 --- a/os_if/linux/nan/src/os_if_nan.c +++ b/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 diff --git a/umac/nan/core/src/nan_api.c b/umac/nan/core/src/nan_api.c index fe251a975864..8dd6ff9130ca 100644 --- a/umac/nan/core/src/nan_api.c +++ b/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))