qcacmn: Fix race while accessing the serialization timer cmd pointer
If two threads T1 and T2 are trying to stop the serialization timer, both can get the timer while holding lock. Timer cmd pointer is set to NULL after releasing lock. Now if a third thread T3 is trying to start the timer at same time, it may get the timer as soon as T1 make cmd NULL and adds its cmd pointer to the timer in the list. But T2, which was also trying to stop the timer can stop the timer and set cmd back to NULL again. Thus T3 will not have the timer in the timer list. Now when driver try to abort/flush the command it will not find the timer and In case timer is not found the command is not freed, leading to vdev ref leak. To fix this stop and update the timer while holding lock. Change-Id: I363a4d36181328be310c7c980c981302501a9453 CRs-Fixed: 2376733
Cette révision appartient à :
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2019 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
|
||||
@@ -648,20 +648,19 @@ wlan_serialization_find_and_update_timer(
|
||||
(ser_timer->cmd->vdev != cmd->vdev))
|
||||
continue;
|
||||
|
||||
qdf_timer_mod(&ser_timer->timer,
|
||||
cmd->cmd_timeout_duration);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
qdf_timer_mod(&ser_timer->timer,
|
||||
cmd->cmd_timeout_duration);
|
||||
ser_debug("Updating the timer for cmd type:%d, id: %d",
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
ser_debug("Updated the timer for cmd type:%d, id: %d",
|
||||
cmd->cmd_type, cmd->cmd_id);
|
||||
} else {
|
||||
else
|
||||
ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type);
|
||||
}
|
||||
|
||||
exit:
|
||||
return status;
|
||||
@@ -706,19 +705,18 @@ wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
|
||||
(ser_timer->cmd->vdev != cmd->vdev))
|
||||
continue;
|
||||
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
status = wlan_serialization_stop_timer(ser_timer);
|
||||
break;
|
||||
}
|
||||
|
||||
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",
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
ser_debug("Stopped timer for cmd_type %d cmd id %d",
|
||||
cmd->cmd_type, cmd->cmd_id);
|
||||
} else {
|
||||
ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type);
|
||||
}
|
||||
else
|
||||
ser_err("Can't find timer for cmd_type %d cmd id %d",
|
||||
cmd->cmd_type, cmd->cmd_id);
|
||||
|
||||
exit:
|
||||
return status;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2019 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
|
||||
@@ -555,11 +555,17 @@ wlan_ser_cancel_non_scan_cmd(
|
||||
|
||||
qdf_status = wlan_serialization_find_and_stop_timer(
|
||||
psoc, &cmd_list->cmd);
|
||||
if (QDF_STATUS_SUCCESS != qdf_status) {
|
||||
ser_err("Can't fix timer for active cmd");
|
||||
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
||||
ser_err("Can't find timer for active cmd");
|
||||
status = WLAN_SER_CMD_NOT_FOUND;
|
||||
/*
|
||||
* This should not happen, as an active command
|
||||
* should always have the timer.
|
||||
*/
|
||||
QDF_BUG(0);
|
||||
break;
|
||||
}
|
||||
|
||||
status = WLAN_SER_CMD_IN_ACTIVE_LIST;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2019 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
|
||||
@@ -271,11 +271,17 @@ wlan_ser_cancel_scan_cmd(
|
||||
|
||||
qdf_status = wlan_serialization_find_and_stop_timer(
|
||||
psoc, &cmd_list->cmd);
|
||||
if (QDF_STATUS_SUCCESS != qdf_status) {
|
||||
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
||||
ser_err("Can't fix timer for active cmd");
|
||||
status = WLAN_SER_CMD_NOT_FOUND;
|
||||
/*
|
||||
* This should not happen, as an active command
|
||||
* should always have the timer.
|
||||
*/
|
||||
QDF_BUG(0);
|
||||
break;
|
||||
}
|
||||
|
||||
status = WLAN_SER_CMD_IN_ACTIVE_LIST;
|
||||
}
|
||||
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur