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
This commit is contained in:
@@ -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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* 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
|
* pmo_core_update_wow_initial_wake_up() - update wow initial wake up
|
||||||
* @psoc_ctx: Pointer to objmgr psoc handle
|
* @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
|
* Return: None
|
||||||
*/
|
*/
|
||||||
static inline
|
static inline
|
||||||
void pmo_core_update_wow_initial_wake_up(struct pmo_psoc_priv_obj *psoc_ctx,
|
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
|
qdf_atomic_set(&psoc_ctx->wow.wow_initial_wake_up, value);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pmo_core_get_wow_initial_wake_up() - Get wow initial wake up
|
* pmo_core_get_wow_initial_wake_up() - Get wow initial wake up
|
||||||
* @psoc_ctx: Pointer to objmgr psoc handle
|
* @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
|
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;
|
return qdf_atomic_read(&psoc_ctx->wow.wow_initial_wake_up);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEATURE_WLAN_EXTSCAN
|
#ifdef FEATURE_WLAN_EXTSCAN
|
||||||
|
@@ -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);
|
wow_mode = pmo_core_is_wow_enabled(psoc_ctx);
|
||||||
pmo_debug("wow mode %d", wow_mode);
|
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 target was not suspended, bail out */
|
||||||
if (!pmo_tgt_is_target_suspended(psoc)) {
|
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);
|
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);
|
pmo_psoc_put_ref(psoc);
|
||||||
out:
|
out:
|
||||||
@@ -1445,7 +1445,7 @@ void pmo_core_psoc_handle_initial_wake_up(void *cb_ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
psoc_ctx = pmo_psoc_get_priv(psoc);
|
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:
|
out:
|
||||||
pmo_exit();
|
pmo_exit();
|
||||||
|
@@ -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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* 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_suspend;
|
||||||
qdf_event_t target_resume;
|
qdf_event_t target_resume;
|
||||||
int wow_nack;
|
int wow_nack;
|
||||||
bool wow_initial_wake_up;
|
atomic_t wow_initial_wake_up;
|
||||||
qdf_wake_lock_t wow_wake_lock;
|
qdf_wake_lock_t wow_wake_lock;
|
||||||
/*
|
/*
|
||||||
* currently supports only vdev 0.
|
* currently supports only vdev 0.
|
||||||
|
@@ -187,6 +187,8 @@ QDF_STATUS pmo_psoc_object_created_notification(
|
|||||||
status = QDF_STATUS_E_FAILURE;
|
status = QDF_STATUS_E_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qdf_atomic_init(&psoc_ctx->wow.wow_initial_wake_up);
|
||||||
/* Register PMO tx ops*/
|
/* Register PMO tx ops*/
|
||||||
target_if_pmo_register_tx_ops(&psoc_ctx->pmo_tx_ops);
|
target_if_pmo_register_tx_ops(&psoc_ctx->pmo_tx_ops);
|
||||||
out:
|
out:
|
||||||
|
Reference in New Issue
Block a user