From aa6303e509923e9ffb381c3f9f3086aaec5c1cc5 Mon Sep 17 00:00:00 2001 From: Vivek Date: Wed, 12 Sep 2018 15:44:14 +0530 Subject: [PATCH] qcacmn: Make access to serialization timers atomic The serialization timers can be accessed from multiple contexts when adding and removing commands to/from the serialization queues. So the access to the serialization timers should be atomic to protect the same timers being used for multiple commands. The serialization timers are maintained per psoc and are protected with psoc timer locks. Also the serialization lock APIs are updated to take the lock object pointer as an argument Change-Id: Ibdb41818fde9318fca6bbc92a536858364639365 CRs-Fixed: 2313039 --- .../src/wlan_serialization_api.c | 20 ++++----- .../src/wlan_serialization_internal.c | 45 ++++++++++++------- .../src/wlan_serialization_main.c | 6 ++- .../src/wlan_serialization_non_scan.c | 11 ++--- .../src/wlan_serialization_scan.c | 11 ++--- .../src/wlan_serialization_utils.c | 39 +++++----------- .../src/wlan_serialization_utils_i.h | 21 ++++----- 7 files changed, 76 insertions(+), 77 deletions(-) diff --git a/umac/cmn_services/serialization/src/wlan_serialization_api.c b/umac/cmn_services/serialization/src/wlan_serialization_api.c index c8613cd3b273..379425a77228 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_api.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_api.c @@ -617,7 +617,7 @@ wlan_serialization_non_scan_cmd_status( /* Look in the pdev non scan active queue */ queue = &pdev_q->active_list; - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); node = wlan_serialization_find_cmd( queue, WLAN_SER_MATCH_CMD_TYPE, @@ -641,7 +641,7 @@ wlan_serialization_non_scan_cmd_status( cmd_status = wlan_serialization_is_cmd_in_active_pending( cmd_in_active, cmd_in_pending); - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); ser_exit(); return cmd_status; @@ -813,7 +813,7 @@ wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev) pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); cmd_in_active = wlan_serialization_is_cmd_in_vdev_list( @@ -826,7 +826,7 @@ wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev) status = wlan_serialization_is_cmd_in_active_pending( cmd_in_active, cmd_in_pending); - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); ser_exit(); return status; @@ -857,7 +857,7 @@ wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev) pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); cmd_in_active = !qdf_list_empty(&pdev_q->active_list); cmd_in_pending = !qdf_list_empty(&pdev_q->pending_list); @@ -865,7 +865,7 @@ wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev) status = wlan_serialization_is_cmd_in_active_pending( cmd_in_active, cmd_in_pending); - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); return status; } @@ -910,7 +910,7 @@ wlan_serialization_get_scan_cmd_using_scan_id( pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); if (is_scan_cmd_from_active_queue) queue = &pdev_q->active_list; @@ -931,7 +931,7 @@ wlan_serialization_get_scan_cmd_using_scan_id( } } - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); release_vdev_ref: wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); @@ -980,7 +980,7 @@ void *wlan_serialization_get_active_cmd( pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type); - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); queue = &pdev_q->active_list; @@ -997,7 +997,7 @@ void *wlan_serialization_get_active_cmd( umac_cmd = cmd_list->cmd.umac_cmd; } - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); release_vdev_ref: wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); diff --git a/umac/cmn_services/serialization/src/wlan_serialization_internal.c b/umac/cmn_services/serialization/src/wlan_serialization_internal.c index bfa31a8102db..2285f5f35168 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_internal.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_internal.c @@ -164,12 +164,12 @@ wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd) cmd->is_high_priority, cmd->is_blocking); - wlan_serialization_acquire_lock(pdev_queue); + wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); active_queue = wlan_serialization_is_active_cmd_allowed(cmd); if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) { - wlan_serialization_release_lock(pdev_queue); + wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); ser_err("duplicate command, can't enqueue"); goto error; } @@ -177,7 +177,7 @@ wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd) if (wlan_serialization_remove_front( &pdev_queue->cmd_pool_list, &nnode) != QDF_STATUS_SUCCESS) { - wlan_serialization_release_lock(pdev_queue); + wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); ser_err("Failed to get cmd buffer from global pool"); goto error; } @@ -216,7 +216,7 @@ wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd) &cmd_list->cmd_in_use); } - wlan_serialization_release_lock(pdev_queue); + wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); if (WLAN_SER_CMD_ACTIVE == status) wlan_serialization_activate_cmd(cmd_list, @@ -463,7 +463,7 @@ wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd, cmd->is_high_priority, cmd->is_blocking); - wlan_serialization_acquire_lock(pdev_queue); + wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) qdf_status = wlan_ser_remove_scan_cmd( @@ -474,7 +474,7 @@ wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd, } if (qdf_status != QDF_STATUS_SUCCESS) { - wlan_serialization_release_lock(pdev_queue); + wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); status = WLAN_SER_CMD_NOT_FOUND; goto error; } @@ -520,7 +520,7 @@ wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd, blocking_cmd_waiting); } - wlan_serialization_release_lock(pdev_queue); + wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); /* Call cmd cb for remove request*/ if (cmd_bkup.cmd_cb) { @@ -674,6 +674,8 @@ wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, * be unique and For non-scan command, there should be only one active * command per pdev */ + wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); + for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { ser_timer = &psoc_ser_obj->timers[i]; if (!(ser_timer->cmd) || @@ -681,14 +683,21 @@ wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, (ser_timer->cmd->cmd_type != cmd->cmd_type) || (ser_timer->cmd->vdev != cmd->vdev)) continue; - status = wlan_serialization_stop_timer(ser_timer); - ser_debug("\n Stopping timer for cmd type:%d, id: %d", - cmd->cmd_type, cmd->cmd_id); + + status = QDF_STATUS_SUCCESS; break; } - if (QDF_STATUS_SUCCESS != status) + wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); + + if (QDF_IS_STATUS_SUCCESS(status)) { + status = wlan_serialization_stop_timer(ser_timer); + ser_debug("\n Stopping timer for cmd type:%d, id: %d", + cmd->cmd_type, cmd->cmd_id); + } else { ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type); + } + error: exit: @@ -721,6 +730,8 @@ wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); + wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); + for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { /* Keep trying timer */ ser_timer = &psoc_ser_obj->timers[i]; @@ -729,22 +740,26 @@ wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, /* Remember timer is pointing to command */ ser_timer->cmd = cmd; + status = QDF_STATUS_SUCCESS; + break; + } + + wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); + + if (QDF_IS_STATUS_SUCCESS(status)) { qdf_timer_init(NULL, &ser_timer->timer, wlan_serialization_timer_handler, ser_timer, QDF_TIMER_TYPE_SW); qdf_timer_mod(&ser_timer->timer, - cmd->cmd_timeout_duration); + cmd->cmd_timeout_duration); ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", cmd->cmd_type, cmd->cmd_id, cmd->is_high_priority, cmd->is_blocking); - - status = QDF_STATUS_SUCCESS; - break; } error: diff --git a/umac/cmn_services/serialization/src/wlan_serialization_main.c b/umac/cmn_services/serialization/src/wlan_serialization_main.c index d31c1b1e5ad2..4c6554967a86 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_main.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_main.c @@ -520,6 +520,7 @@ QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc) ser_soc_obj->timers = NULL; ser_soc_obj->max_active_cmds = 0; + wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); error: ser_exit(); return status; @@ -550,6 +551,7 @@ QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc) goto error; } + wlan_serialization_create_lock(&ser_soc_obj->timer_lock); status = QDF_STATUS_SUCCESS; error: @@ -708,7 +710,7 @@ static QDF_STATUS wlan_serialization_pdev_create_handler( for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { pdev_queue = &ser_pdev_obj->pdev_q[index]; - qdf_spinlock_create(&pdev_queue->pdev_queue_lock); + wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock); switch (index) { case SER_PDEV_QUEUE_COMP_SCAN: @@ -825,7 +827,7 @@ static QDF_STATUS wlan_serialization_pdev_destroy_handler( wlan_serialization_destroy_pdev_list(pdev_queue); wlan_serialization_destroy_cmd_pool(pdev_queue); - qdf_spinlock_destroy(&pdev_queue->pdev_queue_lock); + wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); } qdf_mem_free(ser_pdev_obj); diff --git a/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c b/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c index 83a24070ea1b..33830b00f6db 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c @@ -498,7 +498,7 @@ wlan_ser_cancel_non_scan_cmd( else ser_debug("Can't find psoc"); - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); qsize = wlan_serialization_list_size(pdev_queue); while (!wlan_serialization_list_empty(pdev_queue) && qsize--) { @@ -554,7 +554,8 @@ wlan_ser_cancel_non_scan_cmd( */ if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION, &cmd_list->cmd_in_use)) { - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock( + &pdev_q->pdev_queue_lock); status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION; goto error; } @@ -607,7 +608,7 @@ wlan_ser_cancel_non_scan_cmd( } nnode = pnode; - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); /* * call pending cmd's callback to notify that * it is being removed @@ -626,7 +627,7 @@ wlan_ser_cancel_non_scan_cmd( WLAN_SER_CB_RELEASE_MEM_CMD); } - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); if (!is_active_queue) status = WLAN_SER_CMD_IN_PENDING_LIST; @@ -635,7 +636,7 @@ wlan_ser_cancel_non_scan_cmd( break; } - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); error: ser_exit(); diff --git a/umac/cmn_services/serialization/src/wlan_serialization_scan.c b/umac/cmn_services/serialization/src/wlan_serialization_scan.c index 292fcf1acf34..e748f8bdd951 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_scan.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_scan.c @@ -186,7 +186,7 @@ wlan_ser_cancel_scan_cmd( else ser_debug("Can't find psoc"); - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); qsize = wlan_serialization_list_size(queue); while (!wlan_serialization_list_empty(queue) && qsize--) { @@ -242,7 +242,8 @@ wlan_ser_cancel_scan_cmd( */ if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION, &cmd_list->cmd_in_use)) { - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock( + &pdev_q->pdev_queue_lock); status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION; goto error; } @@ -284,7 +285,7 @@ wlan_ser_cancel_scan_cmd( } nnode = pnode; - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); /* * call pending cmd's callback to notify that * it is being removed @@ -303,13 +304,13 @@ wlan_ser_cancel_scan_cmd( WLAN_SER_CB_RELEASE_MEM_CMD); } - wlan_serialization_acquire_lock(pdev_q); + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); if (!is_active_queue) status = WLAN_SER_CMD_IN_PENDING_LIST; } - wlan_serialization_release_lock(pdev_q); + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); error: ser_exit(); diff --git a/umac/cmn_services/serialization/src/wlan_serialization_utils.c b/umac/cmn_services/serialization/src/wlan_serialization_utils.c index 13c480bf919d..5fc615d8d5b1 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_utils.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_utils.c @@ -1140,6 +1140,8 @@ QDF_STATUS wlan_serialization_cleanup_all_timers( goto error; } + wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); + for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { ser_timer = &psoc_ser_obj->timers[i]; if (!ser_timer->cmd) @@ -1151,6 +1153,7 @@ QDF_STATUS wlan_serialization_cleanup_all_timers( } } + wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); error: ser_exit(); return status; @@ -1783,53 +1786,33 @@ error: } QDF_STATUS -wlan_serialization_acquire_lock( - struct wlan_serialization_pdev_queue *pdev_queue) +wlan_serialization_acquire_lock(qdf_spinlock_t *lock) { - if (!pdev_queue) { - ser_err("invalid object"); - return QDF_STATUS_E_FAILURE; - } - qdf_spin_lock_bh(&pdev_queue->pdev_queue_lock); + qdf_spin_lock_bh(lock); return QDF_STATUS_SUCCESS; } QDF_STATUS -wlan_serialization_release_lock( - struct wlan_serialization_pdev_queue *pdev_queue) +wlan_serialization_release_lock(qdf_spinlock_t *lock) { - if (!pdev_queue) { - ser_err("invalid object"); - return QDF_STATUS_E_FAILURE; - } - qdf_spin_unlock_bh(&pdev_queue->pdev_queue_lock); + qdf_spin_unlock_bh(lock); return QDF_STATUS_SUCCESS; } QDF_STATUS -wlan_serialization_create_lock( - struct wlan_serialization_pdev_queue *pdev_queue) +wlan_serialization_create_lock(qdf_spinlock_t *lock) { - if (!pdev_queue) { - ser_err("invalid object"); - return QDF_STATUS_E_FAILURE; - } - qdf_spinlock_create(&pdev_queue->pdev_queue_lock); + qdf_spinlock_create(lock); return QDF_STATUS_SUCCESS; } QDF_STATUS -wlan_serialization_destroy_lock( - struct wlan_serialization_pdev_queue *pdev_queue) +wlan_serialization_destroy_lock(qdf_spinlock_t *lock) { - if (!pdev_queue) { - ser_err("invalid object"); - return QDF_STATUS_E_FAILURE; - } - qdf_spinlock_destroy(&pdev_queue->pdev_queue_lock); + qdf_spinlock_destroy(lock); return QDF_STATUS_SUCCESS; } diff --git a/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h b/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h index 4382680112bc..b324c86176f1 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h +++ b/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h @@ -784,6 +784,7 @@ struct wlan_ser_psoc_obj { wlan_serialization_apply_rules_cb apply_rules_cb[WLAN_SER_CMD_MAX]; struct wlan_serialization_timer *timers; uint8_t max_active_cmds; + qdf_spinlock_t timer_lock; }; /** @@ -1202,42 +1203,38 @@ QDF_STATUS wlan_serialization_peek_next( /** * wlan_serialization_acquire_lock() - Acquire lock to the given queue - * @pdev_queue: Pointer to the pdev queue + * @lock: Pointer to the lock * * Return: QDF_STATUS success or failure */ QDF_STATUS -wlan_serialization_acquire_lock( - struct wlan_serialization_pdev_queue *pdev_queue); +wlan_serialization_acquire_lock(qdf_spinlock_t *lock); /** * wlan_serialization_release_lock() - Release lock to the given queue - * @pdev_queue: Pointer to the pdev queue + * @lock: Pointer to the lock * * Return: QDF_STATUS success or failure */ QDF_STATUS -wlan_serialization_release_lock( - struct wlan_serialization_pdev_queue *pdev_queue); +wlan_serialization_release_lock(qdf_spinlock_t *lock); /** * wlan_serialization_create_lock() - Init the lock to the given queue - * @pdev_queue: Pointer to the pdev queue + * @lock: Pointer to the lock * * Return: QDF_STATUS success or failure */ QDF_STATUS -wlan_serialization_create_lock( - struct wlan_serialization_pdev_queue *pdev_queue); +wlan_serialization_create_lock(qdf_spinlock_t *lock); /** * wlan_serialization_destroy_lock() - Deinit the lock to the given queue - * @pdev_queue: Pointer to the pdev queue + * @lock: Pointer to the lock * * Return: QDF_STATUS success or failure */ QDF_STATUS -wlan_serialization_destroy_lock( - struct wlan_serialization_pdev_queue *pdev_queue); +wlan_serialization_destroy_lock(qdf_spinlock_t *lock); #endif #endif