瀏覽代碼

Merge "qcacmn: Check function pointer to avoid NULL point dereference"

Linux Build Service Account 3 年之前
父節點
當前提交
6cd6250991

+ 4 - 0
target_if/spectral/target_if_spectral.h

@@ -2119,6 +2119,10 @@ void target_if_spectral_process_phyerr(
 	}
 
 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
+	if (!p_sops->spectral_process_phyerr) {
+		spectral_err("null spectral_process_phyerr");
+		return;
+	}
 	p_sops->spectral_process_phyerr(spectral, data, datalen,
 					p_rfqual, p_chaninfo,
 					tsf64, acs_stats);

+ 14 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h

@@ -38,6 +38,20 @@ void mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 			       struct wlan_objmgr_peer *peer, uint8_t *mlo_ie,
 			       uint8_t aid);
 
+/**
+ * mlo_get_mlpeer - Get ML peer corresponds to the MLD address
+ * @ml_dev: MLO DEV object
+ * @ml_addr: MLD MAC address
+ *
+ * This API will be used to get the ML peer associated with MLD address.
+ * It will return Null if the peer does not exist for the given MLD address.
+ *
+ * Return: Pointer to the ML peer context structure
+ */
+struct wlan_mlo_peer_context *mlo_get_mlpeer(
+				struct wlan_mlo_dev_context *ml_dev,
+				struct qdf_mac_addr *ml_addr);
+
 /**
  * mlo_peer_attach - Attaches the peer by updating the MLO peer context with
  * the new link information

+ 12 - 7
umac/mlo_mgr/src/wlan_mlo_mgr_aid.c

@@ -227,6 +227,16 @@ QDF_STATUS mlo_peer_free_aid(struct wlan_mlo_dev_context *ml_dev,
 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
+	if (!ml_dev->ap_ctx) {
+		mlo_err("ml_dev->ap_ctx is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (!ml_peer) {
+		mlo_err("ml_peer is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
 	if (!ml_aid_mgr)
 		return QDF_STATUS_E_INVAL;
@@ -522,17 +532,12 @@ void wlan_mlo_vdev_aid_mgr_deinit(struct wlan_mlo_dev_context *ml_dev)
 		return;
 
 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
-		if (!ml_dev->wlan_vdev_list[i])
-			continue;
 
 		if (ml_aid_mgr->aid_mgr[i]) {
 			n = qdf_atomic_read(&ml_aid_mgr->aid_mgr[i]->ref_cnt);
-			mlo_info("Vdev ID %d, AID mgr ref cnt %d",
-				 wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]),
-				 n);
+			mlo_info("AID mgr ref cnt %d", n);
 		} else {
-			mlo_err("Vdev ID %d, doesn't have associated AID mgr",
-				wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]));
+			mlo_err("ID %d, doesn't have associated AID mgr", i);
 			continue;
 		}
 		wlan_vdev_aid_mgr_free(ml_aid_mgr->aid_mgr[i]);

+ 65 - 41
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c

@@ -98,11 +98,21 @@ static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
 {
 	struct peer_discon_notify_s peer_disconn;
 	QDF_STATUS status;
-
-	peer_disconn.peer = peer;
-	status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev, &peer_disconn);
-	if (status != QDF_STATUS_SUCCESS)
+	struct wlan_objmgr_vdev *vdev;
+	enum QDF_OPMODE opmode;
+
+	vdev = wlan_peer_get_vdev(peer);
+	opmode = wlan_vdev_mlme_get_opmode(vdev);
+
+	if (opmode == QDF_SAP_MODE) {
+		peer_disconn.peer = peer;
+		status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev,
+				       &peer_disconn);
+		if (status != QDF_STATUS_SUCCESS)
+			wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
+	} else {
 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
+	}
 }
 
 QDF_STATUS
@@ -480,7 +490,7 @@ QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 				uint16_t aid)
 {
 	struct wlan_mlo_dev_context *ml_dev;
-	struct wlan_mlo_peer_context *ml_peer;
+	struct wlan_mlo_peer_context *ml_peer = NULL;
 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
 	struct wlan_objmgr_vdev *vdev_link;
 	QDF_STATUS status;
@@ -494,17 +504,19 @@ QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 	if (QDF_IS_STATUS_ERROR(status))
 		return QDF_STATUS_E_FAILURE;
 
-	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
-		vdev_link = link_vdevs[i];
-		if (!vdev_link) {
-			mlo_debug("vdev_link is null");
-			continue;
-		}
+	if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) {
+		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+			vdev_link = link_vdevs[i];
+			if (!vdev_link) {
+				mlo_debug("vdev_link is null");
+				continue;
+			}
 
-		if (wlan_vdev_is_peer_create_allowed(vdev_link)
-			!= QDF_STATUS_SUCCESS) {
-			mlo_dev_release_link_vdevs(link_vdevs);
-			return QDF_STATUS_E_INVAL;
+			if (wlan_vdev_is_peer_create_allowed(vdev_link)
+					!= QDF_STATUS_SUCCESS) {
+				mlo_dev_release_link_vdevs(link_vdevs);
+				return QDF_STATUS_E_INVAL;
+			}
 		}
 	}
 
@@ -518,27 +530,35 @@ QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 		}
 	}
 
-	/* Allocate MLO peer */
-	ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
-	if (!ml_peer) {
-		mlo_dev_release_link_vdevs(link_vdevs);
-		return QDF_STATUS_E_NOMEM;
+	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)) {
+		ml_peer = mlo_get_mlpeer(
+				ml_dev,
+				(struct qdf_mac_addr *)&link_peer->mldaddr[0]);
 	}
 
-	qdf_atomic_init(&ml_peer->ref_cnt);
-	mlo_peer_lock_create(ml_peer);
-	ml_peer->ml_dev = ml_dev;
-	ml_peer->mlpeer_state = ML_PEER_CREATED;
-	ml_peer->max_links = ml_info->num_partner_links;
-	ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
-	ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
-	qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
-			 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
-	/* Allocate AID */
-	if (aid == (uint16_t)-1)
-		mlo_peer_allocate_aid(ml_dev, ml_peer);
-	else
-		ml_peer->assoc_id = aid;
+	if (!ml_peer) {
+		/* Allocate MLO peer */
+		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
+		if (!ml_peer) {
+			mlo_dev_release_link_vdevs(link_vdevs);
+			return QDF_STATUS_E_NOMEM;
+		}
+
+		qdf_atomic_init(&ml_peer->ref_cnt);
+		mlo_peer_lock_create(ml_peer);
+		ml_peer->ml_dev = ml_dev;
+		ml_peer->mlpeer_state = ML_PEER_CREATED;
+		ml_peer->max_links = ml_info->num_partner_links;
+		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
+		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
+		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
+				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
+		/* Allocate AID */
+		if (aid == (uint16_t)-1)
+			mlo_peer_allocate_aid(ml_dev, ml_peer);
+		else
+			ml_peer->assoc_id = aid;
+	}
 
 	/* Populate Link peer pointer, peer MAC address,
 	 * MLD address. HW link ID, update ref count
@@ -551,13 +571,17 @@ QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
 	mlo_peer_populate_link_peer(ml_peer, link_peer);
 
-	/* Attach MLO peer to ML Peer table */
-	status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
-	if (status != QDF_STATUS_SUCCESS) {
-		mlo_reset_link_peer(ml_peer, link_peer);
-		mlo_peer_free(ml_peer);
-		mlo_dev_release_link_vdevs(link_vdevs);
-		return status;
+	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
+		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
+			!wlan_vdev_mlme_is_mlo_link_vdev(vdev))) {
+		/* Attach MLO peer to ML Peer table */
+		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
+		if (status != QDF_STATUS_SUCCESS) {
+			mlo_reset_link_peer(ml_peer, link_peer);
+			mlo_peer_free(ml_peer);
+			mlo_dev_release_link_vdevs(link_vdevs);
+			return status;
+		}
 	}
 
 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {

+ 1 - 1
umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c

@@ -72,7 +72,7 @@ static inline struct wlan_mlo_peer_context *wlan_mlo_peer_get_next_mlpeer(
 	return next_peer;
 }
 
-static inline struct wlan_mlo_peer_context *mlo_get_mlpeer(
+struct wlan_mlo_peer_context *mlo_get_mlpeer(
 				struct wlan_mlo_dev_context *ml_dev,
 				struct qdf_mac_addr *ml_addr)
 {

+ 32 - 11
umac/mlo_mgr/src/wlan_mlo_mgr_sta.c

@@ -272,11 +272,6 @@ QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
 	struct wlan_mlo_sta *sta_ctx = NULL;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
-	if (qdf_mem_cmp(vdev->vdev_mlme.macaddr,
-			vdev->vdev_mlme.linkaddr,
-			QDF_MAC_ADDR_SIZE))
-		return wlan_cm_start_connect(vdev, req);
-
 	mlo_dev_ctx = vdev->mlo_dev_ctx;
 	if (mlo_dev_ctx)
 		sta_ctx = mlo_dev_ctx->sta_ctx;
@@ -515,7 +510,8 @@ void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
 		}
 		if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
 			if (mlo_dev_ctx->sta_ctx->assoc_rsp.ptr) {
-				qdf_mem_free(mlo_dev_ctx->sta_ctx->assoc_rsp.ptr);
+				qdf_mem_free(
+					mlo_dev_ctx->sta_ctx->assoc_rsp.ptr);
 				mlo_dev_ctx->sta_ctx->assoc_rsp.ptr = NULL;
 			}
 			mlo_dev_ctx->sta_ctx->assoc_rsp.len =
@@ -526,9 +522,11 @@ void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
 				QDF_ASSERT(0);
 				return;
 			}
-			qdf_mem_copy(mlo_dev_ctx->sta_ctx->assoc_rsp.ptr,
-				     rsp->connect_ies.assoc_rsp.ptr,
-				     rsp->connect_ies.assoc_rsp.len);
+			if (rsp->connect_ies.assoc_rsp.ptr)
+				qdf_mem_copy(
+					mlo_dev_ctx->sta_ctx->assoc_rsp.ptr,
+					rsp->connect_ies.assoc_rsp.ptr,
+					rsp->connect_ies.assoc_rsp.len);
 		}
 		mlo_send_link_connect(vdev, mlo_dev_ctx,
 				      &rsp->connect_ies.assoc_rsp,
@@ -609,8 +607,8 @@ mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
 		if (!mlo_dev_ctx->wlan_vdev_list[i])
 			continue;
 
-		if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links) &&
-		    mlo_dev_ctx->wlan_vdev_list[i] != mlo_get_assoc_link_vdev(mlo_dev_ctx))
+		if (mlo_dev_ctx->wlan_vdev_list[i] !=
+				mlo_get_assoc_link_vdev(mlo_dev_ctx))
 			wlan_cm_disconnect_sync(mlo_dev_ctx->wlan_vdev_list[i],
 						CM_MLO_DISCONNECT, reason_code);
 	}
@@ -850,6 +848,29 @@ void mlo_handle_disconnect_resp(struct wlan_mlo_dev_context *mlo_dev_ctx,
 				struct wlan_cm_discon_rsp *resp)
 {
 /* If it is secondary link then delete vdev object from mlo device. */
+	enum wlan_cm_source source;
+	enum wlan_reason_code reason_code;
+	uint8_t i = 0;
+
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		if (!mlo_dev_ctx->wlan_vdev_list[i])
+			continue;
+
+		if (wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i])) {
+			if (wlan_vdev_mlme_is_mlo_link_vdev(
+					mlo_dev_ctx->wlan_vdev_list[i])) {
+				source = resp->req.req.source;
+				reason_code = resp->req.req.reason_code;
+				wlan_cm_disconnect(
+						mlo_dev_ctx->wlan_vdev_list[i],
+						source, reason_code, NULL);
+				mlo_dev_lock_release(mlo_dev_ctx);
+				return;
+			}
+		}
+	}
+	mlo_dev_lock_release(mlo_dev_ctx);
 }
 #else
 static