Răsfoiți Sursa

qcacld-3.0: Fix offload_enabled flag per vdev

When WLAN_AP_DISCONNECT event is not processed during IPA resource
unloading inprogress, IPA offload disable is not invoked.
And WLAN_AP_CONNECT event comes later, since a new interface is setup,
the previous IPA offload enable status is not checked properly, and it
causes FW crash because IPA offload enabled twice.
Fix to maintain the IPA offload enabled flag per vdev, instead of per
interface.

Change-Id: I9ba7eceb5b1b69490e14f97871b30ea6a89c28f6
CRs-Fixed: 1091525
Prakash Dhavali 8 ani în urmă
părinte
comite
89d406da14
1 a modificat fișierele cu 36 adăugiri și 25 ștergeri
  1. 36 25
      core/hdd/src/wlan_hdd_ipa.c

+ 36 - 25
core/hdd/src/wlan_hdd_ipa.c

@@ -246,7 +246,6 @@ struct hdd_ipa_iface_context {
 	qdf_spinlock_t interface_lock;
 	uint32_t ifa_address;
 	struct hdd_ipa_iface_stats stats;
-	uint32_t offload_enabled;
 };
 
 struct hdd_ipa_stats {
@@ -347,7 +346,6 @@ struct uc_op_work_struct {
 	struct work_struct work;
 	struct op_msg_type *msg;
 };
-static uint8_t vdev_to_iface[CSR_ROAM_SESSION_MAX];
 
 /**
  * struct uc_rt_debug_info
@@ -448,6 +446,9 @@ struct hdd_ipa_priv {
 	/* IPA UC doorbell registers paddr */
 	qdf_dma_addr_t tx_comp_doorbell_paddr;
 	qdf_dma_addr_t rx_ready_doorbell_paddr;
+
+	uint8_t vdev_to_iface[CSR_ROAM_SESSION_MAX];
+	bool vdev_offload_enabled[CSR_ROAM_SESSION_MAX];
 };
 
 /**
@@ -1611,21 +1612,31 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
  * Return: none
  */
 static void hdd_ipa_uc_offload_enable_disable(hdd_adapter_t *adapter,
-			uint32_t offload_type, uint32_t enable)
+			uint32_t offload_type, bool enable)
 {
+	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
 	struct sir_ipa_offload_enable_disable ipa_offload_enable_disable;
 	struct hdd_ipa_iface_context *iface_context = NULL;
+	uint8_t session_id;
 
-	if (!adapter)
+	if (!adapter || !hdd_ipa)
 		return;
 
 	iface_context = adapter->ipa_context;
+	session_id = adapter->sessionId;
+
+	if (!iface_context) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "Interface context is NULL");
+		return;
+	}
 
-	if (!iface_context || (enable == iface_context->offload_enabled)) {
+	if (enable == hdd_ipa->vdev_offload_enabled[session_id]) {
 		/* IPA offload status is already set as desired */
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "IPA offload status is already set: (offload_type=%d, vdev_id=%d, enable=%d)",
-			    offload_type, adapter->sessionId, enable);
+			    "%s: (offload_type=%d, vdev_id=%d, enable=%d)",
+			    "IPA offload status is already set",
+			    offload_type, session_id, enable);
 		return;
 	}
 
@@ -1639,7 +1650,7 @@ static void hdd_ipa_uc_offload_enable_disable(hdd_adapter_t *adapter,
 	qdf_mem_zero(&ipa_offload_enable_disable,
 		sizeof(ipa_offload_enable_disable));
 	ipa_offload_enable_disable.offload_type = offload_type;
-	ipa_offload_enable_disable.vdev_id = adapter->sessionId;
+	ipa_offload_enable_disable.vdev_id = session_id;
 	ipa_offload_enable_disable.enable = enable;
 
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
@@ -1659,7 +1670,7 @@ static void hdd_ipa_uc_offload_enable_disable(hdd_adapter_t *adapter,
 			    ipa_offload_enable_disable.enable);
 	} else {
 		/* Update the IPA offload status */
-		iface_context->offload_enabled =
+		hdd_ipa->vdev_offload_enabled[session_id] =
 			ipa_offload_enable_disable.enable;
 	}
 }
@@ -2764,7 +2775,7 @@ static void __hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt,
 
 		if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
 			session_id = (uint8_t)skb->cb[0];
-			iface_id = vdev_to_iface[session_id];
+			iface_id = hdd_ipa->vdev_to_iface[session_id];
 			HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_INFO_HIGH,
 				"IPA_RECEIVE: session_id=%u, iface_id=%u",
 				session_id, iface_id);
@@ -2883,7 +2894,6 @@ static void hdd_ipa_send_pkt_to_tl(
 		struct ipa_rx_data *ipa_tx_desc)
 {
 	struct hdd_ipa_priv *hdd_ipa = iface_context->hdd_ipa;
-	uint8_t interface_id;
 	hdd_adapter_t *adapter = NULL;
 	qdf_nbuf_t skb;
 
@@ -2910,7 +2920,6 @@ static void hdd_ipa_send_pkt_to_tl(
 		return;
 	}
 
-	interface_id = adapter->sessionId;
 	++adapter->stats.tx_packets;
 
 	qdf_spin_unlock_bh(&iface_context->interface_lock);
@@ -3944,11 +3953,11 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 		    !hdd_ipa->sta_connected) {
 			qdf_mutex_release(&hdd_ipa->event_lock);
 			hdd_ipa_uc_offload_enable_disable(adapter,
-				SIR_STA_RX_DATA_OFFLOAD, 1);
+				SIR_STA_RX_DATA_OFFLOAD, true);
 			qdf_mutex_acquire(&hdd_ipa->event_lock);
 		}
 
-		vdev_to_iface[adapter->sessionId] =
+		hdd_ipa->vdev_to_iface[adapter->sessionId] =
 			((struct hdd_ipa_iface_context *)
 			(adapter->ipa_context))->iface_id;
 
@@ -3983,11 +3992,11 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 		if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
 			qdf_mutex_release(&hdd_ipa->event_lock);
 			hdd_ipa_uc_offload_enable_disable(adapter,
-				SIR_AP_RX_DATA_OFFLOAD, 1);
+				SIR_AP_RX_DATA_OFFLOAD, true);
 			qdf_mutex_acquire(&hdd_ipa->event_lock);
 		}
 
-		vdev_to_iface[adapter->sessionId] =
+		hdd_ipa->vdev_to_iface[adapter->sessionId] =
 			((struct hdd_ipa_iface_context *)
 			(adapter->ipa_context))->iface_id;
 
@@ -4023,9 +4032,10 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 		    (hdd_ipa->sap_num_connected_sta > 0)) {
 			qdf_mutex_release(&hdd_ipa->event_lock);
 			hdd_ipa_uc_offload_enable_disable(adapter,
-				SIR_STA_RX_DATA_OFFLOAD, 0);
+				SIR_STA_RX_DATA_OFFLOAD, false);
 			qdf_mutex_acquire(&hdd_ipa->event_lock);
-			vdev_to_iface[adapter->sessionId] = CSR_ROAM_SESSION_MAX;
+			hdd_ipa->vdev_to_iface[adapter->sessionId] =
+				CSR_ROAM_SESSION_MAX;
 		}
 
 		hdd_ipa_cleanup_iface(adapter->ipa_context);
@@ -4065,9 +4075,10 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 		if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
 			qdf_mutex_release(&hdd_ipa->event_lock);
 			hdd_ipa_uc_offload_enable_disable(adapter,
-				SIR_AP_RX_DATA_OFFLOAD, 0);
+				SIR_AP_RX_DATA_OFFLOAD, false);
 			qdf_mutex_acquire(&hdd_ipa->event_lock);
-			vdev_to_iface[adapter->sessionId] = CSR_ROAM_SESSION_MAX;
+			hdd_ipa->vdev_to_iface[adapter->sessionId] =
+				CSR_ROAM_SESSION_MAX;
 		}
 
 		hdd_ipa_cleanup_iface(adapter->ipa_context);
@@ -4101,7 +4112,7 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 				hdd_ipa_uc_offload_enable_disable(
 					hdd_get_adapter(hdd_ipa->hdd_ctx,
 							QDF_STA_MODE),
-					SIR_STA_RX_DATA_OFFLOAD, 1);
+					SIR_STA_RX_DATA_OFFLOAD, true);
 				qdf_mutex_acquire(&hdd_ipa->event_lock);
 			}
 
@@ -4119,7 +4130,7 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 						hdd_get_adapter(
 							hdd_ipa->hdd_ctx,
 							QDF_STA_MODE),
-						SIR_STA_RX_DATA_OFFLOAD, 0);
+						SIR_STA_RX_DATA_OFFLOAD, false);
 				} else {
 					qdf_mutex_release(&hdd_ipa->event_lock);
 				}
@@ -4200,7 +4211,7 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
 				hdd_ipa_uc_offload_enable_disable(
 					hdd_get_adapter(hdd_ipa->hdd_ctx,
 							QDF_STA_MODE),
-					SIR_STA_RX_DATA_OFFLOAD, 0);
+					SIR_STA_RX_DATA_OFFLOAD, false);
 		} else {
 			qdf_mutex_release(&hdd_ipa->event_lock);
 		}
@@ -4374,11 +4385,11 @@ QDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx)
 			hdd_ipa_adapter_2_client[i].prod_client;
 		iface_context->iface_id = i;
 		iface_context->adapter = NULL;
-		iface_context->offload_enabled = 0;
 		qdf_spinlock_create(&iface_context->interface_lock);
 	}
 	for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
-		vdev_to_iface[i] = CSR_ROAM_SESSION_MAX;
+		hdd_ipa->vdev_to_iface[i] = CSR_ROAM_SESSION_MAX;
+		hdd_ipa->vdev_offload_enabled[i] = false;
 	}
 
 	INIT_WORK(&hdd_ipa->pm_work, hdd_ipa_pm_flush);