qcacmn: Make sure vdev manager delete isn't executed in softirq context
Currently host driver will call wlan_objmgr_peer_release_ref() in tgt_mgmt_txrx_tx_completion_handler() to decrease peer reference count when management frame TX completion is received. When the last pending reference is management frame in some corner cases, below call stack will be triggered: BUG: scheduling while atomic: swapper/0/0/0x00000102 [ 105.368065] Call trace: [ 105.368079] dump_backtrace+0x0/0x1b4 [ 105.368087] show_stack+0x14/0x1c [ 105.368096] dump_stack+0xd4/0x10c [ 105.368105] __schedule_bug+0x50/0x70 [ 105.368113] __schedule+0x980/0xc04 [ 105.368119] schedule+0x70/0x90 [ 105.368126] schedule_timeout+0x3c/0x5f4 [ 105.368133] wait_for_common+0xb0/0x138 [ 105.368139] wait_for_completion+0x14/0x1c [ 105.368148] synchronize_srcu_expedited+0xc8/0x100 [ 105.368153] synchronize_srcu+0xa4/0x17c [ 105.368161] wakeup_source_remove+0x54/0x74 [ 105.368840] __qdf_wake_lock_destroy+0x14/0x28 [wlan] [ 105.369518] wma_vdev_deinit+0x104/0x144 [wlan] [ 105.370190] wma_vdev_detach_callback+0xd8/0x108 [wlan] [ 105.370870] vdevmgr_vdev_delete_rsp_handle+0x48/0x54 [wlan] [ 105.371557] mlme_vdev_ops_ext_hdl_delete_rsp+0x2c/0x44 [wlan] [ 105.372245] tgt_vdev_mgr_delete_response_handler+0xc/0x14 [wlan] [ 105.372928] target_if_vdev_mgr_delete_send+0x2cc/0x2d8 [wlan] [ 105.373613] tgt_vdev_mgr_delete_send+0x15c/0x19c [wlan] [ 105.374296] vdev_mgr_delete_send+0x44/0x118 [wlan] [ 105.374975] vdevmgr_mlme_ext_hdl_destroy+0x7c/0x128 [wlan] [ 105.375662] mlme_vdev_ops_ext_hdl_destroy+0x2c/0x44 [wlan] [ 105.376341] mlme_vdev_obj_destroy_handler+0x2c/0xc0 [wlan] [ 105.377027] wlan_objmgr_vdev_release_ref+0x128/0x250 [wlan] [ 105.377710] wlan_objmgr_peer_obj_free+0x1d4/0x1dc [wlan] [ 105.378402] wlan_objmgr_peer_release_ref+0x1f8/0x22c [wlan] [ 105.379085] tgt_mgmt_txrx_tx_completion_handler+0x194/0x1c0 [wlan] [ 105.379751] wma_mgmt_tx_ack_comp_hdlr+0xdc/0x190 [wlan] [ 105.380425] ol_tx_desc_frame_free_nonstd+0x58/0xec [wlan] [ 105.381100] ol_tx_single_completion_handler+0x27c/0x2bc [wlan] [ 105.381796] htt_t2h_msg_handler+0xeec/0x1280 [wlan] [ 105.382506] htc_rx_completion_handler+0x8b0/0x9c4 [wlan] [ 105.383202] hif_pci_ce_recv_data+0x198/0x234 [wlan] [ 105.383899] ce_engine_service_reg+0x110/0x444 [wlan] [ 105.384595] ce_per_engine_service+0x70/0x104 [wlan] [ 105.385289] hif_napi_poll+0x94/0x3b4 [wlan] [ 105.385899] hdd_napi_poll+0x28/0x34 [wlan] [ 105.385928] net_rx_action+0x110/0x480 [ 105.385948] __do_softirq+0x1e8/0x39c [ 105.385962] irq_exit+0xcc/0xd8 [ 105.385982] __handle_domain_irq+0x84/0xbc [ 105.386001] gic_handle_irq+0x168/0x1b8 [ 105.386015] el1_irq+0xb0/0x124 [ 105.386035] lpm_cpuidle_enter+0x4fc/0x538 [ 105.386051] cpuidle_enter_state+0x1c0/0x338 [ 105.386063] cpuidle_enter+0x18/0x20 [ 105.386084] do_idle+0x1a0/0x288 Due to some wlan chip doesn't support wmi_service_sync_delete_cmds capability, it will call target_if_vdev_mgr_delete_response_send() directly to process further and doesn't exit softirq context, then cause thread schedule under softirq context. To avoid above race condition, let vdev manager delete response scheduled by driver thread for MCC case. Change-Id: I143b585bf0e7b7d3bfbe94656ea1c548cfd2efd8 CRs-Fixed: 3300663
此提交包含在:
@@ -499,20 +499,99 @@ static QDF_STATUS target_if_vdev_mgr_start_send(
|
||||
}
|
||||
|
||||
static QDF_STATUS target_if_vdev_mgr_delete_response_send(
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t vdev_id,
|
||||
struct wlan_lmac_if_mlme_rx_ops *rx_ops)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
|
||||
struct vdev_delete_response rsp = {0};
|
||||
|
||||
rsp.vdev_id = wlan_vdev_get_id(vdev);
|
||||
rsp.vdev_id = vdev_id;
|
||||
status = rx_ops->vdev_mgr_delete_response(psoc, &rsp);
|
||||
target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef SERIALIZE_VDEV_RESP
|
||||
static QDF_STATUS
|
||||
target_if_vdev_mgr_del_rsp_post_flush_cb(struct scheduler_msg *msg)
|
||||
{
|
||||
/* Dummy */
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
target_if_vdev_mgr_del_rsp_post_cb(struct scheduler_msg *msg)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_lmac_if_mlme_rx_ops *rx_ops;
|
||||
uint8_t vdev_id;
|
||||
|
||||
if (!msg || !msg->bodyptr) {
|
||||
mlme_err("Msg or Msg bodyptr is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
psoc = msg->bodyptr;
|
||||
|
||||
vdev_id = msg->bodyval;
|
||||
if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
|
||||
mlme_err("Invalid VDEV_ID %d", vdev_id);
|
||||
return;
|
||||
}
|
||||
|
||||
rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
|
||||
if (!rx_ops) {
|
||||
mlme_err("No Rx Ops");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't try to get vdev as it's already deleted */
|
||||
target_if_vdev_mgr_delete_response_send(psoc, vdev_id, rx_ops);
|
||||
}
|
||||
|
||||
static void target_if_vdev_mgr_delete_rsp_post_ctx(
|
||||
struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
struct scheduler_msg msg = {0};
|
||||
|
||||
msg.callback = (scheduler_msg_process_fn_t)
|
||||
target_if_vdev_mgr_del_rsp_post_cb;
|
||||
msg.bodyptr = psoc;
|
||||
msg.bodyval = vdev_id;
|
||||
msg.flush_callback =
|
||||
target_if_vdev_mgr_del_rsp_post_flush_cb;
|
||||
|
||||
if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
|
||||
QDF_MODULE_ID_TARGET_IF,
|
||||
QDF_MODULE_ID_TARGET_IF, &msg) ==
|
||||
QDF_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
mlme_err("Failed to enqueue vdev delete response");
|
||||
}
|
||||
|
||||
static void
|
||||
target_if_vdev_mgr_delete_rsp_handler(
|
||||
struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t vdev_id,
|
||||
struct wlan_lmac_if_mlme_rx_ops *rx_ops)
|
||||
{
|
||||
target_if_vdev_mgr_delete_rsp_post_ctx(psoc, vdev_id);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
target_if_vdev_mgr_delete_rsp_handler(
|
||||
struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t vdev_id,
|
||||
struct wlan_lmac_if_mlme_rx_ops *rx_ops)
|
||||
{
|
||||
target_if_vdev_mgr_delete_response_send(psoc, vdev_id, rx_ops);
|
||||
}
|
||||
#endif
|
||||
|
||||
static QDF_STATUS target_if_vdev_mgr_delete_send(
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
struct vdev_delete_params *param)
|
||||
@@ -567,7 +646,8 @@ static QDF_STATUS target_if_vdev_mgr_delete_send(
|
||||
WLAN_SOC_F_TESTMODE_ENABLE)) {
|
||||
target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp,
|
||||
DELETE_RESPONSE_BIT);
|
||||
target_if_vdev_mgr_delete_response_send(vdev, rx_ops);
|
||||
target_if_vdev_mgr_delete_rsp_handler(psoc, vdev_id,
|
||||
rx_ops);
|
||||
}
|
||||
} else {
|
||||
vdev_rsp->expire_time = 0;
|
||||
|
新增問題並參考
封鎖使用者