Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 797b21b3 authored by Bapiraju Alla's avatar Bapiraju Alla Committed by snandini
Browse files

qcacld-3.0: Add debug infra to detect reference leaks for dev_hold

Currently there is no debug infra to detect the API that caused the
reference leak for dev_hold. So, It very hard to debug/fix the
reference leak issues.

To address this, add debug_infra for dev_hold and dev_put calls in
the driver. This change also fixes the few reference leaks with
hdd_for_each_adapter_dev_held_safe.

Change-Id: Icf1adf53c3bd11c715111494bac958c541ef87ea
CRs-Fixed: 2825558
parent 40c3372f
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021 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
@@ -2797,6 +2797,8 @@ void cds_incr_arp_stats_tx_tgt_delivered(void)
{
	struct hdd_context *hdd_ctx;
	struct hdd_adapter *adapter, *next_adapter = NULL;
	wlan_net_dev_ref_dbgid dbgid =
			NET_DEV_HOLD_CDS_INCR_ARP_STATS_TX_TGT_DELIVERED;

	hdd_ctx = gp_cds_context->hdd_context;
	if (!hdd_ctx) {
@@ -2804,14 +2806,15 @@ void cds_incr_arp_stats_tx_tgt_delivered(void)
		return;
	}

	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
					   dbgid) {
		if (adapter->device_mode == QDF_STA_MODE) {
			dev_put(adapter->dev);
			hdd_adapter_dev_put_debug(adapter, dbgid);
			if (next_adapter)
				dev_put(next_adapter->dev);
				hdd_adapter_dev_put_debug(next_adapter, dbgid);
			break;
		}
		dev_put(adapter->dev);
		hdd_adapter_dev_put_debug(adapter, dbgid);
	}

	if (adapter)
@@ -2827,6 +2830,8 @@ void cds_incr_arp_stats_tx_tgt_acked(void)
{
	struct hdd_context *hdd_ctx;
	struct hdd_adapter *adapter, *next_adapter = NULL;
	wlan_net_dev_ref_dbgid dbgid =
			NET_DEV_HOLD_CDS_INCR_ARP_STATS_TX_TGT_ACKED;

	hdd_ctx = gp_cds_context->hdd_context;
	if (!hdd_ctx) {
@@ -2834,14 +2839,15 @@ void cds_incr_arp_stats_tx_tgt_acked(void)
		return;
	}

	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
					   dbgid) {
		if (adapter->device_mode == QDF_STA_MODE) {
			dev_put(adapter->dev);
			hdd_adapter_dev_put_debug(adapter, dbgid);
			if (next_adapter)
				dev_put(next_adapter->dev);
				hdd_adapter_dev_put_debug(next_adapter, dbgid);
			break;
		}
		dev_put(adapter->dev);
		hdd_adapter_dev_put_debug(adapter, dbgid);
	}

	if (adapter)
+119 −41
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021 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
@@ -438,6 +438,81 @@ enum hdd_auth_key_mgmt {
	HDD_AUTH_KEY_MGMT_CCKM = BIT(2)
};

/**
 * wlan_net_dev_ref_dbgid - Debug IDs to detect net device reference leaks
 */
/*
 * New value added to the enum must also be reflected in function
 *  net_dev_ref_debug_string_from_id()
 */
typedef enum {
	NET_DEV_HOLD_ID_RESERVED = 0,
	NET_DEV_HOLD_GET_STA_CONNECTION_IN_PROGRESS = 1,
	NET_DEV_HOLD_CHECK_DFS_CHANNEL_FOR_ADAPTER = 2,
	NET_DEV_HOLD_GET_SAP_OPERATING_BAND = 3,
	NET_DEV_HOLD_RECOVERY_NOTIFIER_CALL = 4,
	NET_DEV_HOLD_IS_ANY_STA_CONNECTING = 5,
	NET_DEV_HOLD_SAP_DESTROY_CTX_ALL = 6,
	NET_DEV_HOLD_DRV_CMD_MAX_TX_POWER = 7,
	NET_DEV_HOLD_IPA_SET_TX_FLOW_INFO = 8,
	NET_DEV_HOLD_SET_RPS_CPU_MASK = 9,
	NET_DEV_HOLD_DFS_INDICATE_RADAR = 10,
	NET_DEV_HOLD_MAX_STA_INTERFACE_UP_COUNT_REACHED = 11,
	NET_DEV_HOLD_IS_CHAN_SWITCH_IN_PROGRESS = 12,
	NET_DEV_HOLD_STA_DESTROY_CTX_ALL = 13,
	NET_DEV_HOLD_CHECK_FOR_EXISTING_MACADDR = 14,
	NET_DEV_HOLD_DEINIT_ALL_ADAPTERS = 15,
	NET_DEV_HOLD_STOP_ALL_ADAPTERS = 16,
	NET_DEV_HOLD_RESET_ALL_ADAPTERS = 17,
	NET_DEV_HOLD_IS_ANY_INTERFACE_OPEN = 18,
	NET_DEV_HOLD_START_ALL_ADAPTERS = 19,
	NET_DEV_HOLD_GET_ADAPTER_BY_RAND_MACADDR = 20,
	NET_DEV_HOLD_GET_ADAPTER_BY_MACADDR = 21,
	NET_DEV_HOLD_GET_ADAPTER_BY_VDEV = 22,
	NET_DEV_HOLD_ADAPTER_GET_BY_REFERENCE = 23,
	NET_DEV_HOLD_GET_ADAPTER_BY_IFACE_NAME = 24,
	NET_DEV_HOLD_GET_ADAPTER = 25,
	NET_DEV_HOLD_GET_OPERATING_CHAN_FREQ = 26,
	NET_DEV_HOLD_UNREGISTER_WEXT_ALL_ADAPTERS = 27,
	NET_DEV_HOLD_ABORT_MAC_SCAN_ALL_ADAPTERS = 28,
	NET_DEV_HOLD_ABORT_SCHED_SCAN_ALL_ADAPTERS = 29,
	NET_DEV_HOLD_GET_FIRST_VALID_ADAPTER = 30,
	NET_DEV_HOLD_CLEAR_RPS_CPU_MASK = 31,
	NET_DEV_HOLD_BUS_BW_WORK_HANDLER = 32,
	NET_DEV_HOLD_DISPLAY_NETIF_QUEUE_HISTORY_COMPACT = 33,
	NET_DEV_HOLD_DISPLAY_NETIF_QUEUE_HISTORY = 34,
	NET_DEV_HOLD_CLEAR_NETIF_QUEUE_HISTORY = 35,
	NET_DEV_HOLD_UNSAFE_CHANNEL_RESTART_SAP = 36,
	NET_DEV_HOLD_INDICATE_MGMT_FRAME = 37,
	NET_DEV_HOLD_STATE_INFO_DUMP = 38,
	NET_DEV_HOLD_DISABLE_ROAMING = 39,
	NET_DEV_HOLD_ENABLE_ROAMING = 40,
	NET_DEV_HOLD_AUTO_SHUTDOWN_ENABLE = 41,
	NET_DEV_HOLD_GET_CON_SAP_ADAPTER = 42,
	NET_DEV_HOLD_IS_ANY_ADAPTER_CONNECTED = 43,
	NET_DEV_HOLD_IS_ROAMING_IN_PROGRESS = 44,
	NET_DEV_HOLD_DEL_P2P_INTERFACE = 45,
	NET_DEV_HOLD_IS_NDP_ALLOWED = 46,
	NET_DEV_HOLD_NDI_OPEN = 47,
	NET_DEV_HOLD_SEND_OEM_REG_RSP_NLINK_MSG = 48,
	NET_DEV_HOLD_PERIODIC_STA_STATS_DISPLAY = 49,
	NET_DEV_HOLD_SUSPEND_WLAN = 50,
	NET_DEV_HOLD_RESUME_WLAN = 51,
	NET_DEV_HOLD_SSR_RESTART_SAP = 52,
	NET_DEV_HOLD_SEND_DEFAULT_SCAN_IES = 53,
	NET_DEV_HOLD_CFG80211_SUSPEND_WLAN = 54,
	NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_STA = 55,
	NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP = 56,
	NET_DEV_HOLD_CACHE_STATION_STATS_CB = 57,
	NET_DEV_HOLD_DISPLAY_TXRX_STATS = 58,
	NET_DEV_HOLD_CDS_INCR_ARP_STATS_TX_TGT_DELIVERED = 59,
	NET_DEV_HOLD_CDS_INCR_ARP_STATS_TX_TGT_ACKED = 60,
	NET_DEV_HOLD_GET_MODE_SPECIFIC_INTERFACE_COUNT = 61,

	/* Keep it at the end */
	NET_DEV_HOLD_ID_MAX
} wlan_net_dev_ref_dbgid;

/**
 * struct hdd_tx_rx_histogram - structure to keep track of tx and rx packets
 *				received over 100ms intervals
@@ -1393,6 +1468,7 @@ struct hdd_adapter {
	uint8_t gro_disallowed[DP_MAX_RX_THREADS];
	uint8_t gro_flushed[DP_MAX_RX_THREADS];
	bool delete_in_progress;
	uint8_t net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX];
};

#define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station)
@@ -2302,16 +2378,24 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb,
			       void *context);

/**
 * __hdd_take_ref_and_fetch_front_adapter - Helper macro to lock, fetch front
 * adapter, take ref and unlock.
 * @hdd_ctx: the global HDD context
 * @adapter: an hdd_adapter pointer to use as a cursor
 * hdd_adapter_dev_hold_debug - Debug API to call dev_hold
 * @adapter: hdd_adapter pointer
 * @dbgid: Debug ID corresponding to API that is requesting the dev_hold
 *
 * Return: none
 */
#define __hdd_take_ref_and_fetch_front_adapter(hdd_ctx, adapter) \
	qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock), \
	hdd_get_front_adapter_no_lock(hdd_ctx, &adapter), \
	(adapter) ? dev_hold(adapter->dev) : (false), \
	qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock)
void hdd_adapter_dev_hold_debug(struct hdd_adapter *adapter,
				wlan_net_dev_ref_dbgid dbgid);

/**
 * hdd_adapter_dev_put_debug - Debug API to call dev_put
 * @adapter: hdd_adapter pointer
 * @dbgid: Debug ID corresponding to API that is requesting the dev_put
 *
 * Return: none
 */
void hdd_adapter_dev_put_debug(struct hdd_adapter *adapter,
			       wlan_net_dev_ref_dbgid dbgid);

/**
 * __hdd_take_ref_and_fetch_front_adapter_safe - Helper macro to lock, fetch
@@ -2319,26 +2403,16 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb,
 * @hdd_ctx: the global HDD context
 * @adapter: an hdd_adapter pointer to use as a cursor
 * @next_adapter: hdd_adapter pointer to next adapter
 * @dbgid: debug ID to detect reference leaks
 */
#define __hdd_take_ref_and_fetch_front_adapter_safe(hdd_ctx, adapter, \
						    next_adapter) \
						    next_adapter, dbgid) \
	qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock), \
	hdd_get_front_adapter_no_lock(hdd_ctx, &adapter), \
	(adapter) ? dev_hold(adapter->dev) : (false), \
	(adapter) ? hdd_adapter_dev_hold_debug(adapter, dbgid) : (false), \
	hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &next_adapter), \
	(next_adapter) ? dev_hold(next_adapter->dev) : (false), \
	qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock)

/**
 * __hdd_take_ref_and_fetch_next_adapter - Helper macro to lock, fetch next
 * adapter, take ref and unlock.
 * @hdd_ctx: the global HDD context
 * @adapter: an hdd_adapter pointer to use as a cursor
 */
#define __hdd_take_ref_and_fetch_next_adapter(hdd_ctx, adapter) \
	qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock), \
	hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &adapter), \
	(adapter) ? dev_hold(adapter->dev) : (false), \
	(next_adapter) ? hdd_adapter_dev_hold_debug(next_adapter, dbgid) : \
			 (false), \
	qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock)

/**
@@ -2347,13 +2421,15 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb,
 * @hdd_ctx: the global HDD context
 * @adapter: hdd_adapter pointer to use as a cursor
 * @next_adapter: hdd_adapter pointer to next adapter
 * @dbgid: debug ID to detect reference leaks
 */
#define __hdd_take_ref_and_fetch_next_adapter_safe(hdd_ctx, adapter, \
						   next_adapter) \
						   next_adapter, dbgid) \
	qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock), \
	adapter = next_adapter, \
	hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &next_adapter), \
	(next_adapter) ? dev_hold(next_adapter->dev) : (false), \
	(next_adapter) ? hdd_adapter_dev_hold_debug(next_adapter, dbgid) : \
			 (false), \
	qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock)

/**
@@ -2377,25 +2453,27 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb,
 * inside the loop body then the dev_hold has been invoked.
 *
 *                           ***** NOTE *****
 * Before the end of each iteration, dev_put(adapter->dev) must be
 * called. Not calling this will keep hold of a reference, thus preventing
 * unregister of the netdevice. If the loop is terminated in between with
 * return/goto/break statements, dev_put(next_adapter->dev) must be done
 * along with dev_put(adapter->dev) before termination of the loop.
 * Before the end of each iteration, hdd_adapter_dev_put_debug(adapter, dbgid)
 * must be called. Not calling this will keep hold of a reference, thus
 * preventing unregister of the netdevice. If the loop is terminated in
 * between with return/goto/break statements,
 * hdd_adapter_dev_put_debug(next_adapter, dbgid) must be done along with
 * hdd_adapter_dev_put_debug(adapter, dbgid) before termination of the loop.
 *
 * Usage example:
 *        hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
 *  hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, dbgid) {
 *        <work involving adapter>
 *        <some more work>
 *               dev_put(adapter->dev)
 *        hdd_adapter_dev_put_debug(adapter, dbgid)
 *  }
 */
#define hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) \
#define hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, \
					   dbgid) \
	for (__hdd_take_ref_and_fetch_front_adapter_safe(hdd_ctx, adapter, \
							 next_adapter); \
							 next_adapter, dbgid); \
	     __hdd_is_adapter_valid(adapter); \
	     __hdd_take_ref_and_fetch_next_adapter_safe(hdd_ctx, adapter, \
							next_adapter))
							next_adapter, dbgid))

/**
 * wlan_hdd_get_adapter_by_vdev_id_from_objmgr() - Fetch adapter from objmgr
+12 −7
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021 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
@@ -401,13 +401,16 @@ struct hdd_adapter *hdd_get_sta_connection_in_progress(
{
	struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
	struct hdd_station_ctx *hdd_sta_ctx;
	wlan_net_dev_ref_dbgid dbgid =
				NET_DEV_HOLD_GET_STA_CONNECTION_IN_PROGRESS;

	if (!hdd_ctx) {
		hdd_err("HDD context is NULL");
		return NULL;
	}

	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
					   dbgid) {
		hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
		if ((QDF_STA_MODE == adapter->device_mode) ||
		    (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
@@ -416,9 +419,10 @@ struct hdd_adapter *hdd_get_sta_connection_in_progress(
			    hdd_sta_ctx->conn_info.conn_state) {
				hdd_debug("vdev_id %d: Connection is in progress",
					  adapter->vdev_id);
				dev_put(adapter->dev);
				hdd_adapter_dev_put_debug(adapter, dbgid);
				if (next_adapter)
					dev_put(next_adapter->dev);
					hdd_adapter_dev_put_debug(next_adapter,
								  dbgid);
				return adapter;
			} else if ((eConnectionState_Associated ==
				   hdd_sta_ctx->conn_info.conn_state) &&
@@ -427,13 +431,14 @@ struct hdd_adapter *hdd_get_sta_connection_in_progress(
							adapter->vdev_id)) {
				hdd_debug("vdev_id %d: Key exchange is in progress",
					  adapter->vdev_id);
				dev_put(adapter->dev);
				hdd_adapter_dev_put_debug(adapter, dbgid);
				if (next_adapter)
					dev_put(next_adapter->dev);
					hdd_adapter_dev_put_debug(next_adapter,
								  dbgid);
				return adapter;
			}
		}
		dev_put(adapter->dev);
		hdd_adapter_dev_put_debug(adapter, dbgid);
	}
	return NULL;
}
+17 −10
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021 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
@@ -5599,8 +5599,11 @@ static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
	struct hdd_adapter *adapter, *next_adapter = NULL;
	struct hdd_ap_ctx *ap_ctx;
	struct hdd_station_ctx *sta_ctx;
	wlan_net_dev_ref_dbgid dbgid =
				NET_DEV_HOLD_CHECK_DFS_CHANNEL_FOR_ADAPTER;
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
					   dbgid) {
		if ((device_mode == adapter->device_mode) &&
		    (device_mode == QDF_SAP_MODE)) {
			ap_ctx =
@@ -5617,9 +5620,10 @@ static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
				hdd_ctx->pdev,
				ap_ctx->operating_chan_freq)) {
				hdd_err("SAP running on DFS channel");
				dev_put(adapter->dev);
				hdd_adapter_dev_put_debug(adapter, dbgid);
				if (next_adapter)
					dev_put(next_adapter->dev);
					hdd_adapter_dev_put_debug(next_adapter,
								  dbgid);
				return true;
			}
		}
@@ -5638,13 +5642,14 @@ static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
				hdd_ctx->pdev,
				sta_ctx->conn_info.chan_freq))) {
				hdd_err("client connected on DFS channel");
				dev_put(adapter->dev);
				hdd_adapter_dev_put_debug(adapter, dbgid);
				if (next_adapter)
					dev_put(next_adapter->dev);
					hdd_adapter_dev_put_debug(next_adapter,
								  dbgid);
				return true;
			}
		}
		dev_put(adapter->dev);
		hdd_adapter_dev_put_debug(adapter, dbgid);
	}
	return false;
@@ -11117,10 +11122,12 @@ uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
	struct hdd_adapter *adapter, *next_adapter = NULL;
	uint32_t  operating_chan_freq;
	uint8_t sap_operating_band = 0;
	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_SAP_OPERATING_BAND;
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
					   dbgid) {
		if (adapter->device_mode != QDF_SAP_MODE) {
			dev_put(adapter->dev);
			hdd_adapter_dev_put_debug(adapter, dbgid);
			continue;
		}
@@ -11133,7 +11140,7 @@ uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
		else
			sap_operating_band = BAND_ALL;
		dev_put(adapter->dev);
		hdd_adapter_dev_put_debug(adapter, dbgid);
	}
	return sap_operating_band;
+10 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2020-2021, 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 above
@@ -50,6 +50,7 @@ static int wlan_hdd_recovery_notifier_call(struct notifier_block *block,
	struct wlan_objmgr_vdev *vdev;
	struct hdd_hang_event_fixed_param *cmd;
	struct hdd_scan_fixed_param *cmd_scan;
	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_RECOVERY_NOTIFIER_CALL;

	if (!data)
		return NOTIFY_STOP_MASK;
@@ -76,10 +77,11 @@ static int wlan_hdd_recovery_notifier_call(struct notifier_block *block,
		hdd_hang_data->offset += total_len;
	}

	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
					   dbgid) {
		vdev = hdd_objmgr_get_vdev(adapter);
		if (!vdev) {
			dev_put(adapter->dev);
			hdd_adapter_dev_put_debug(adapter, dbgid);
			continue;
		}
		total_len = sizeof(*cmd);
@@ -87,7 +89,10 @@ static int wlan_hdd_recovery_notifier_call(struct notifier_block *block,
		if (hdd_hang_data->offset + total_len >
				QDF_WLAN_HANG_FW_OFFSET) {
			hdd_objmgr_put_vdev(vdev);
			dev_put(adapter->dev);
			hdd_adapter_dev_put_debug(adapter, dbgid);
			if (next_adapter)
				hdd_adapter_dev_put_debug(next_adapter,
							  dbgid);
			return NOTIFY_STOP_MASK;
		}
		cmd = (struct hdd_hang_event_fixed_param *)hdd_buf_ptr;
@@ -100,7 +105,7 @@ static int wlan_hdd_recovery_notifier_call(struct notifier_block *block,
		cmd->vdev_substate = wlan_vdev_mlme_get_substate(vdev);
		hdd_hang_data->offset += total_len;
		hdd_objmgr_put_vdev(vdev);
		dev_put(adapter->dev);
		hdd_adapter_dev_put_debug(adapter, dbgid);
	}

	return NOTIFY_OK;
Loading