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
This commit is contained in:
Abhishek Singh
2021-11-17 10:55:18 +05:30
committed by Madan Koyyalamudi
부모 9cba107914
커밋 3915bd37fb
3개의 변경된 파일27개의 추가작업 그리고 25개의 파일을 삭제

파일 보기

@@ -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;