Bladeren bron

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
Bapiraju Alla 4 jaren geleden
bovenliggende
commit
c1ad30d540
2 gewijzigde bestanden met toevoegingen van 11 en 5 verwijderingen
  1. 1 1
      core/hdd/inc/wlan_hdd_main.h
  2. 10 4
      core/hdd/src/wlan_hdd_main.c

+ 1 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -1529,7 +1529,7 @@ struct hdd_adapter {
 	ol_txrx_rx_fp rx_stack;
 
 	qdf_work_t netdev_features_update_work;
-	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];
 	/* Flag to indicate whether it is a pre cac adapter or not */
 	bool is_pre_cac_adapter;
 	bool delete_in_progress;

+ 10 - 4
core/hdd/src/wlan_hdd_main.c

@@ -5911,7 +5911,8 @@ static void hdd_check_for_net_dev_ref_leak(struct hdd_adapter *adapter)
 
 	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));
@@ -6612,6 +6613,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 	struct net_device *ndev = NULL;
 	struct hdd_adapter *adapter = NULL;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	uint32_t i;
 
 	if (hdd_ctx->current_intf_count >= WLAN_MAX_VDEVS) {
 		/*
@@ -6824,6 +6826,10 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 	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)
@@ -8555,7 +8561,7 @@ void hdd_adapter_dev_hold_debug(struct hdd_adapter *adapter,
 		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,
@@ -8566,14 +8572,14 @@ void hdd_adapter_dev_put_debug(struct hdd_adapter *adapter,
 		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,