Prechádzať zdrojové kódy

qcacld-3.0: Fix spin_lock deadlock issue for resume/wakeup

If resume and fw wakeup happens at the same time.
psoc_ctx->lock maybe doing bottom half operation for resume,
then wakeup interrupt comes on same cpu, the interrupt
handler will also acquire psoc_ctx->lock in
pmo_core_update_wow_initial_wake_up, which cause dead lock.

Using atomic for wow_initial_wake_up, so the interrupt handler
can avoid using spin_lock.

Change-Id: Id0e963a0924415e9660c57a1c1b776d3e609213d
CRs-Fixed: 2624899
Jingxiang Ge 5 rokov pred
rodič
commit
ad6337f2b0

+ 9 - 21
components/pmo/core/inc/wlan_pmo_wow.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020 The Linux Foundation. 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
@@ -486,41 +486,29 @@ bool pmo_core_get_wow_enable_cmd_sent(struct pmo_psoc_priv_obj *psoc_ctx)
 /**
  * pmo_core_update_wow_initial_wake_up() - update wow initial wake up
  * @psoc_ctx: Pointer to objmgr psoc handle
- * @value: true if wow initial wake up is received else false
+ * @value: set to 1 if wow initial wake up is received;
+ *         if clean state, reset it to 0;
  *
  * Return: None
  */
 static inline
 void pmo_core_update_wow_initial_wake_up(struct pmo_psoc_priv_obj *psoc_ctx,
-	bool value)
+	int value)
 {
-	/* Intentionally using irq save since initial wake flag is updated
-	 * from wake msi hard irq handler
-	 */
-	qdf_spin_lock_irqsave(&psoc_ctx->lock);
-	psoc_ctx->wow.wow_initial_wake_up = value;
-	qdf_spin_unlock_irqrestore(&psoc_ctx->lock);
+	qdf_atomic_set(&psoc_ctx->wow.wow_initial_wake_up, value);
 }
 
 /**
  * pmo_core_get_wow_initial_wake_up() - Get wow initial wake up
  * @psoc_ctx: Pointer to objmgr psoc handle
  *
- * Return:  true if wow initial wake up is received else false
+ * Return:  1 if wow initial wake up is received;
+ *          0 if wow iniital wake up is not received;
  */
 static inline
-bool pmo_core_get_wow_initial_wake_up(struct pmo_psoc_priv_obj *psoc_ctx)
+int pmo_core_get_wow_initial_wake_up(struct pmo_psoc_priv_obj *psoc_ctx)
 {
-	bool value;
-
-	/* Intentionally using irq save since initial wake flag is updated
-	 * from wake msi hard irq handler
-	 */
-	qdf_spin_lock_irqsave(&psoc_ctx->lock);
-	value = psoc_ctx->wow.wow_initial_wake_up;
-	qdf_spin_unlock_irqrestore(&psoc_ctx->lock);
-
-	return value;
+	return qdf_atomic_read(&psoc_ctx->wow.wow_initial_wake_up);
 }
 
 #ifdef FEATURE_WLAN_EXTSCAN

+ 3 - 3
components/pmo/core/src/wlan_pmo_suspend_resume.c

@@ -1292,7 +1292,7 @@ QDF_STATUS pmo_core_psoc_bus_resume_req(struct wlan_objmgr_psoc *psoc,
 	wow_mode = pmo_core_is_wow_enabled(psoc_ctx);
 	pmo_debug("wow mode %d", wow_mode);
 
-	pmo_core_update_wow_initial_wake_up(psoc_ctx, false);
+	pmo_core_update_wow_initial_wake_up(psoc_ctx, 0);
 
 	/* If target was not suspended, bail out */
 	if (!pmo_tgt_is_target_suspended(psoc)) {
@@ -1424,7 +1424,7 @@ int pmo_core_psoc_clear_target_wake_up(struct wlan_objmgr_psoc *psoc)
 	}
 
 	psoc_ctx = pmo_psoc_get_priv(psoc);
-	pmo_core_update_wow_initial_wake_up(psoc_ctx, false);
+	pmo_core_update_wow_initial_wake_up(psoc_ctx, 0);
 
 	pmo_psoc_put_ref(psoc);
 out:
@@ -1445,7 +1445,7 @@ void pmo_core_psoc_handle_initial_wake_up(void *cb_ctx)
 	}
 
 	psoc_ctx = pmo_psoc_get_priv(psoc);
-	pmo_core_update_wow_initial_wake_up(psoc_ctx, true);
+	pmo_core_update_wow_initial_wake_up(psoc_ctx, 1);
 
 out:
 	pmo_exit();

+ 2 - 2
components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020 The Linux Foundation. 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
@@ -235,7 +235,7 @@ struct pmo_wow {
 	qdf_event_t target_suspend;
 	qdf_event_t target_resume;
 	int wow_nack;
-	bool wow_initial_wake_up;
+	atomic_t wow_initial_wake_up;
 	qdf_wake_lock_t wow_wake_lock;
 	/*
 	 * currently supports only vdev 0.

+ 2 - 0
components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c

@@ -187,6 +187,8 @@ QDF_STATUS pmo_psoc_object_created_notification(
 		status = QDF_STATUS_E_FAILURE;
 		goto out;
 	}
+
+	qdf_atomic_init(&psoc_ctx->wow.wow_initial_wake_up);
 	/* Register PMO tx ops*/
 	target_if_pmo_register_tx_ops(&psoc_ctx->pmo_tx_ops);
 out: