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

Commit 5f54dfa6 authored by Surabhi Vishnoi's avatar Surabhi Vishnoi Committed by Madan Koyyalamudi
Browse files

qcacld-3.0: Fix deadlock scenario in packet capture mode

Ppdu_stats are received from firmware in softirq context.
While inserting the ppdu_stats into a qdf list, a spinlock
is held for its access, same qdf list is accessed by mon
thread using spinlock. There can be a scenario in which
mon_thread held spinlock for accessing qdf_list and is
interrupted by softirq in which ppdu_stats are received.
This leads to softirq spinning for lock forever leading
to deadlock.

To address this issue, use spin_lock_bh instead of spin_lock.
Also reduce the time for which lock is taken to access the list
for insertion and removal of ppdu_stats.

Change-Id: I52171fe3c1d22a1e9d1ab36daac54d8fa2b96020
CRs-Fixed: 3136901
parent 5d97da49
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
 * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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
@@ -299,9 +299,10 @@ pkt_capture_update_tx_status(
	pktcapture_hdr->nss = vdev_priv->tx_nss;

	/* Remove the ppdu stats from front of list and fill it in tx_status */
	qdf_spin_lock(&vdev_priv->lock_q);
	qdf_spin_lock_bh(&vdev_priv->lock_q);
	if (QDF_STATUS_SUCCESS ==
	    qdf_list_remove_front(&vdev_priv->ppdu_stats_q, &node)) {
		qdf_spin_unlock_bh(&vdev_priv->lock_q);
		q_node = qdf_container_of(
			node, struct pkt_capture_ppdu_stats_q_node, node);
		smu = (htt_ppdu_stats_for_smu_tlv *)(q_node->buf);
@@ -317,8 +318,9 @@ pkt_capture_update_tx_status(
				     2 * sizeof(uint32_t));

		qdf_mem_free(q_node);
	} else {
		qdf_spin_unlock_bh(&vdev_priv->lock_q);
	}
	qdf_spin_unlock(&vdev_priv->lock_q);

skip_ppdu_stats:
	pkt_capture_tx_get_phy_info(pktcapture_hdr, tx_status);
+5 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
 * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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
@@ -227,7 +227,7 @@ pkt_capture_process_ppdu_stats(void *log_data)
	smu = (htt_ppdu_stats_for_smu_tlv *)log_data;
	vdev_priv->tx_nss = smu->nss;

	qdf_spin_lock(&vdev_priv->lock_q);
	qdf_spin_lock_bh(&vdev_priv->lock_q);
	if (qdf_list_size(&vdev_priv->ppdu_stats_q) <
					PPDU_STATS_Q_MAX_SIZE) {
		/*
@@ -235,7 +235,7 @@ pkt_capture_process_ppdu_stats(void *log_data)
		 * we support only 256 bit ba bitmap.
		 */
		if (smu->win_size > 8) {
			qdf_spin_unlock(&vdev_priv->lock_q);
			qdf_spin_unlock_bh(&vdev_priv->lock_q);
			pkt_capture_vdev_put_ref(vdev);
			pkt_capture_err("win size %d > 8 not supported\n",
					smu->win_size);
@@ -247,7 +247,7 @@ pkt_capture_process_ppdu_stats(void *log_data)

		q_node = qdf_mem_malloc(sizeof(*q_node) + stats_len);
		if (q_node == NULL) {
			qdf_spin_unlock(&vdev_priv->lock_q);
			qdf_spin_unlock_bh(&vdev_priv->lock_q);
			pkt_capture_vdev_put_ref(vdev);
			pkt_capture_err("stats node and buf allocation fail\n");
			return;
@@ -258,7 +258,7 @@ pkt_capture_process_ppdu_stats(void *log_data)
		qdf_list_insert_back(&vdev_priv->ppdu_stats_q,
				     &q_node->node);
	}
	qdf_spin_unlock(&vdev_priv->lock_q);
	qdf_spin_unlock_bh(&vdev_priv->lock_q);
	pkt_capture_vdev_put_ref(vdev);
}