qcacmn: Drop disconnect req in INIT state
In case the vdev is already disconnected, the indication to the upper layer, would have been sent as part of previous disconnect/connect failure. If the upper layer is in process of connecting, sending the disconnect indication back again may cause it to incorrectly think it as connect failure. So sending a disconnect indication again is not advisable. So if a new disconnect is received in INIT state, drop the disconnect and return failure. Also remove osif_cm_reset_id_and_src() from osif disconnect to avoid race between disconnect complete of old disconnect and new disconnect request. With osif_cm_reset_id_and_src() old disconnect might also get dropped in osif and with this fix new disconnect will also get dropped, so make sure that last/old disconnect indication is sent to upper layer. Change-Id: Icf7352d8904473329edff9ec124c6197f214f88b CRs-Fixed: 3074093
Этот коммит содержится в:

коммит произвёл
Madan Koyyalamudi

родитель
9cba107914
Коммит
3915bd37fb
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 above
|
||||
@@ -554,20 +555,6 @@ connect_start_fail:
|
||||
return qdf_status_to_os_return(status);
|
||||
}
|
||||
|
||||
static QDF_STATUS osif_cm_send_disconnect(struct wlan_objmgr_vdev *vdev,
|
||||
uint16_t reason)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = osif_cm_reset_id_and_src(vdev);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return qdf_status_to_os_return(status);
|
||||
|
||||
status = mlo_disconnect(vdev, CM_OSIF_DISCONNECT, reason, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev,
|
||||
uint16_t reason)
|
||||
{
|
||||
@@ -578,7 +565,7 @@ int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev,
|
||||
dev->name, vdev_id, reason,
|
||||
ucfg_cm_reason_code_to_str(reason));
|
||||
|
||||
status = osif_cm_send_disconnect(vdev, reason);
|
||||
status = mlo_disconnect(vdev, CM_OSIF_DISCONNECT, reason, NULL);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
osif_err("Disconnect failed with status %d", status);
|
||||
|
||||
|
@@ -602,6 +602,23 @@ cm_handle_discon_req_in_non_connected_state(struct cnx_mgr *cm_ctx,
|
||||
cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, false);
|
||||
cm_flush_pending_request(cm_ctx, DISCONNECT_REQ_PREFIX, false);
|
||||
break;
|
||||
case WLAN_CM_S_INIT:
|
||||
/*
|
||||
* In this case the vdev is already disconnected and thus the
|
||||
* indication to upper layer, would have been sent as part of
|
||||
* previous disconnect/connect failure.
|
||||
*
|
||||
* If upper layer is in process of connecting, sending
|
||||
* disconnect indication back again may cause it to incorrectly
|
||||
* think it as a connect failure. So sending disconnect
|
||||
* indication again is not advisable.
|
||||
*
|
||||
* So no need to do anything here, just return failure and drop
|
||||
* disconnect.
|
||||
*/
|
||||
mlme_info("vdev %d droping disconnect req from source %d in INIT state",
|
||||
wlan_vdev_get_id(cm_ctx->vdev), cm_req->req.source);
|
||||
return QDF_STATUS_E_ALREADY;
|
||||
default:
|
||||
mlme_err("Vdev %d disconnect req in invalid state %d",
|
||||
wlan_vdev_get_id(cm_ctx->vdev),
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 above
|
||||
@@ -92,7 +93,6 @@ static bool cm_state_init_event(void *ctx, uint16_t event,
|
||||
struct cnx_mgr *cm_ctx = ctx;
|
||||
bool event_handled = true;
|
||||
QDF_STATUS status;
|
||||
struct cm_disconnect_req *req;
|
||||
|
||||
switch (event) {
|
||||
case WLAN_CM_SM_EV_CONNECT_REQ:
|
||||
@@ -113,15 +113,13 @@ static bool cm_state_init_event(void *ctx, uint16_t event,
|
||||
cm_disconnect_complete(cm_ctx, data);
|
||||
break;
|
||||
case WLAN_CM_SM_EV_DISCONNECT_REQ:
|
||||
status = cm_add_disconnect_req_to_list(cm_ctx, data);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
/* if fail to add req return failure */
|
||||
event_handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
req = data;
|
||||
cm_send_disconnect_resp(cm_ctx, req->cm_id);
|
||||
cm_handle_discon_req_in_non_connected_state(cm_ctx, data,
|
||||
WLAN_CM_S_INIT);
|
||||
/*
|
||||
* Return not handled as this req need to be dropped and return
|
||||
* failure to the requester
|
||||
*/
|
||||
event_handled = false;
|
||||
break;
|
||||
default:
|
||||
event_handled = false;
|
||||
|
Ссылка в новой задаче
Block a user