1 /* 2 * Copyright (c) 2012-2015, 2020, The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: Implements disconnect specific apis of connection manager 19 */ 20 #include "wlan_cm_main_api.h" 21 #include "wlan_cm_sm.h" 22 #include <wlan_serialization_api.h> 23 24 static QDF_STATUS 25 cm_ser_disconnect_cb(struct wlan_serialization_command *cmd, 26 enum wlan_serialization_cb_reason reason) 27 { 28 QDF_STATUS status = QDF_STATUS_SUCCESS; 29 struct wlan_objmgr_vdev *vdev; 30 31 if (!cmd) { 32 mlme_err("cmd is NULL, reason: %d", reason); 33 QDF_ASSERT(0); 34 return QDF_STATUS_E_NULL_VALUE; 35 } 36 37 vdev = cmd->vdev; 38 39 switch (reason) { 40 case WLAN_SER_CB_ACTIVATE_CMD: 41 /* Post event disconnect active to CM SM */ 42 break; 43 44 case WLAN_SER_CB_CANCEL_CMD: 45 /* command removed from pending list. */ 46 break; 47 48 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 49 mlme_err("Active command timeout cm_id %d", cmd->cmd_id); 50 QDF_ASSERT(0); 51 break; 52 53 case WLAN_SER_CB_RELEASE_MEM_CMD: 54 /* command completed. Release reference of vdev */ 55 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 56 break; 57 58 default: 59 QDF_ASSERT(0); 60 status = QDF_STATUS_E_INVAL; 61 break; 62 } 63 64 return status; 65 } 66 67 #define DISCONNECT_TIMEOUT STOP_RESPONSE_TIMER + DELETE_RESPONSE_TIMER + 1000 68 69 static QDF_STATUS cm_ser_disconnect_req(struct wlan_objmgr_pdev *pdev, 70 struct cnx_mgr *cm_ctx, 71 struct cm_disconnect_req *req) 72 { 73 struct wlan_serialization_command cmd = {0, }; 74 enum wlan_serialization_status ser_cmd_status; 75 QDF_STATUS status; 76 77 status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID); 78 if (QDF_IS_STATUS_ERROR(status)) { 79 mlme_err("unable to get reference"); 80 return status; 81 } 82 83 cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT; 84 cmd.cmd_id = req->cm_id; 85 cmd.cmd_cb = cm_ser_disconnect_cb; 86 cmd.source = WLAN_UMAC_COMP_MLME; 87 cmd.is_high_priority = false; 88 cmd.cmd_timeout_duration = DISCONNECT_TIMEOUT; 89 cmd.vdev = cm_ctx->vdev; 90 91 ser_cmd_status = wlan_serialization_request(&cmd); 92 switch (ser_cmd_status) { 93 case WLAN_SER_CMD_PENDING: 94 /* command moved to pending list.Do nothing */ 95 break; 96 case WLAN_SER_CMD_ACTIVE: 97 /* command moved to active list. Do nothing */ 98 break; 99 default: 100 mlme_err("ser cmd status %d", ser_cmd_status); 101 wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID); 102 103 return QDF_STATUS_E_FAILURE; 104 } 105 106 return QDF_STATUS_SUCCESS; 107 } 108 109 QDF_STATUS cm_disconnect_start(struct cnx_mgr *cm_ctx, 110 struct cm_disconnect_req *req) 111 { 112 struct wlan_objmgr_pdev *pdev; 113 114 /* Interface event */ 115 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 116 if (!pdev) 117 return QDF_STATUS_E_INVAL; 118 119 /* 120 * Interface event, stop scan, disconnect TDLS, P2P roc cleanup 121 */ 122 123 /* Serialize disconnect req, Handle failure status */ 124 cm_ser_disconnect_req(pdev, cm_ctx, req); 125 126 return QDF_STATUS_SUCCESS; 127 } 128 129 QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 130 { 131 /* 132 * call vdev sm to start disconnect. 133 */ 134 return QDF_STATUS_SUCCESS; 135 } 136 137 QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx, 138 struct wlan_cm_discon_rsp *resp) 139 { 140 /* 141 * inform osif, inform interface manager 142 * update fils/wep key and inform legacy, update bcn filter and scan 143 * entry mlme info, blm action and remove from serialization at the end. 144 */ 145 return QDF_STATUS_SUCCESS; 146 } 147 148 QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev, 149 struct wlan_cm_disconnect_req *req) 150 { 151 struct cnx_mgr *cm_ctx = NULL; 152 struct cm_disconnect_req *cm_req = NULL; 153 154 /* 155 * Prepare cm_disconnect_req cm_req, get cm id and inform it to 156 * OSIF. store disconnect req to the cm ctx req_list 157 */ 158 159 return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_REQ, 160 sizeof(*cm_req), cm_req); 161 } 162