qcacld-3.0: Make net_dev_hold_ref_count as atomic

Currently the reference count variable used to detect the net device
reference leaks is not atomic. Because of this, the reference count
updation may not be reliable in multi thread scenario.

To address this, make the net_dev_hold_ref_count increment and
decrement as atomic.

Change-Id: Ifa87177164e87880d0c6d71fb40ca03a3919519e
CRs-Fixed: 2868029
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 4f9565f..33b1587 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1468,7 +1468,7 @@
 	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];
+	qdf_atomic_t net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX];
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station)
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 1d48ecf..6a8cc85 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -5541,7 +5541,8 @@
 
 	for (id = 0; id < NET_DEV_HOLD_ID_MAX; id++) {
 		for (i = 0; i < MAX_NET_DEV_REF_LEAK_ITERATIONS; i++) {
-			if (!adapter->net_dev_hold_ref_count[id])
+			if (!qdf_atomic_read(
+				&adapter->net_dev_hold_ref_count[id]))
 				break;
 			hdd_info("net_dev held for debug id %s",
 				 net_dev_ref_debug_string_from_id(id));
@@ -6233,6 +6234,7 @@
 	struct hdd_adapter *adapter = NULL;
 	u8 intf_count = 0;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	uint32_t i;
 
 	if (hdd_ctx->current_intf_count >= WLAN_MAX_VDEVS) {
 		/*
@@ -6457,6 +6459,10 @@
 	hdd_sta_info_init(&adapter->sta_info_list);
 	hdd_sta_info_init(&adapter->cache_sta_info_list);
 
+	for (i = 0; i < NET_DEV_HOLD_ID_MAX; i++)
+		qdf_atomic_init(
+			&adapter->net_dev_hold_ref_count[NET_DEV_HOLD_ID_MAX]);
+
 	/* Add it to the hdd's session list. */
 	status = hdd_add_adapter_back(hdd_ctx, adapter);
 	if (QDF_STATUS_SUCCESS != status)
@@ -8124,7 +8130,7 @@
 		QDF_BUG(0);
 	}
 	dev_hold(adapter->dev);
-	adapter->net_dev_hold_ref_count[dbgid]++;
+	qdf_atomic_inc(&adapter->net_dev_hold_ref_count[dbgid]);
 }
 
 void hdd_adapter_dev_put_debug(struct hdd_adapter *adapter,
@@ -8135,14 +8141,14 @@
 		QDF_BUG(0);
 	}
 
-	if (adapter->net_dev_hold_ref_count[dbgid] == 0) {
+	if (qdf_atomic_dec_return(
+			&adapter->net_dev_hold_ref_count[dbgid]) < 0) {
 		hdd_err("dev_put detected without dev_hold for debug id: %s",
 			net_dev_ref_debug_string_from_id(dbgid));
 		QDF_BUG(0);
 	}
 
 	dev_put(adapter->dev);
-	adapter->net_dev_hold_ref_count[dbgid]--;
 }
 
 QDF_STATUS hdd_get_front_adapter(struct hdd_context *hdd_ctx,