1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * @file wlan_vdev_mlme_ser.c 21 * This file contains the APIs to support interface between vdev_mlme and 22 * serialization module 23 */ 24 25 #include <qdf_types.h> 26 #include <qdf_status.h> 27 #include <qdf_mem.h> 28 #include <wlan_serialization_api.h> 29 #include <wlan_objmgr_vdev_obj.h> 30 #include <wlan_cmn.h> 31 #include <wlan_mlme_dbg.h> 32 #include <include/wlan_vdev_mlme.h> 33 #include <wlan_vdev_mlme_api.h> 34 #include <wlan_vdev_mlme_ser_if.h> 35 36 enum wlan_serialization_status 37 wlan_vdev_mlme_ser_start_bss(struct wlan_serialization_command *cmd) 38 { 39 struct vdev_mlme_obj *vdev_mlme; 40 41 if (!cmd || !cmd->vdev) { 42 mlme_err("Null input"); 43 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 44 } 45 46 /* 47 * Serialization command filtering logic 48 * a. Cancel any existing start bss cmd in the pending queue 49 * b. If there is an start bss cmd in active queue and 50 * there is no stop bss cmd in pending queue, 51 * then explicitly enqueue a stop bss cmd to avoid back to 52 * back execution of UP cmd. 53 * c. Enqueue the new start bss cmd with serialization 54 */ 55 wlan_vdev_mlme_ser_cancel_request( 56 cmd->vdev, 57 WLAN_SER_CMD_VDEV_START_BSS, 58 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); 59 60 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 61 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(cmd->vdev); 62 if (mlme_vdev_enqueue_exp_ser_cmd(vdev_mlme, 63 WLAN_SER_CMD_VDEV_STOP_BSS)) { 64 mlme_err("Unable to add the exception cmd request"); 65 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 66 } 67 } 68 69 return wlan_serialization_request(cmd); 70 } 71 72 enum wlan_serialization_status 73 wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd) 74 { 75 uint8_t stop_cmd_pending; 76 uint8_t ret; 77 78 if (!cmd || !cmd->vdev) { 79 mlme_err("Null input"); 80 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 81 } 82 /* 83 * Serialization command filtering logic 84 * a. Cancel any existing start/stop/restart command in the pending 85 * queue. 86 * b. If there is a stop cmd in active queue then return 87 * c. Else enqueue the cmd 88 * d. If stop cmd already existed in pending queue then return with 89 * already exists else return the enqueued return value. 90 */ 91 stop_cmd_pending = 92 wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd); 93 wlan_vdev_mlme_ser_cancel_request(cmd->vdev, 94 WLAN_SER_CMD_NONSCAN, 95 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD); 96 97 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 98 mlme_err("Cmd already exist in the active queue"); 99 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 100 } 101 102 ret = wlan_serialization_request(cmd); 103 104 if (stop_cmd_pending && ret == WLAN_SER_CMD_PENDING) 105 return WLAN_SER_CMD_ALREADY_EXISTS; 106 else 107 return ret; 108 } 109 110 enum wlan_serialization_status 111 wlan_vdev_mlme_ser_restart_bss(struct wlan_serialization_command *cmd) 112 { 113 if (!cmd || !cmd->vdev) { 114 mlme_err("Null input"); 115 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 116 } 117 /* 118 * Serialization command filtering logic 119 * a. Cancel any existing RESTART cmd in the pending queue 120 * b. Enqueue the new RESTART cmd 121 */ 122 wlan_vdev_mlme_ser_cancel_request( 123 cmd->vdev, 124 WLAN_SER_CMD_VDEV_RESTART, 125 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); 126 return wlan_serialization_request(cmd); 127 } 128 129 enum wlan_serialization_status 130 wlan_vdev_mlme_ser_connect(struct wlan_serialization_command *cmd) 131 { 132 struct vdev_mlme_obj *vdev_mlme; 133 134 if (!cmd || !cmd->vdev) { 135 mlme_err("Null input"); 136 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 137 } 138 /* 139 * Serialization command filtering logic 140 * a. Cancel any existing CONNECT cmd in the pending queue 141 * b. If there is an CONNECT cmd in active queue and there is no 142 * DISCONNECT cmd in pending queue, then explicitly enqueue a 143 * DISCONNECT cmd to avoid back to back execution of CONNECT cmd. 144 * c. Enqueue the new CONNECT cmd to the pending queue 145 */ 146 wlan_vdev_mlme_ser_cancel_request( 147 cmd->vdev, 148 WLAN_SER_CMD_VDEV_CONNECT, 149 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); 150 151 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 152 vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj( 153 cmd->vdev, WLAN_UMAC_COMP_MLME); 154 if (mlme_vdev_enqueue_exp_ser_cmd(vdev_mlme, 155 WLAN_SER_CMD_VDEV_DISCONNECT)) { 156 mlme_err("Unable to add the exception cmd request"); 157 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 158 } 159 } 160 161 return wlan_serialization_request(cmd); 162 } 163 164 enum wlan_serialization_status 165 wlan_vdev_mlme_ser_disconnect(struct wlan_serialization_command *cmd) 166 { 167 if (!cmd || !cmd->vdev) { 168 mlme_err("Null input"); 169 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 170 } 171 /* 172 * Serialization command filtering logic 173 * a.Cancel any existing CONNECT/DISCONNECT/RESTART command in the 174 * pending queue 175 * b.If there is a DISCONNECT cmd in active queue then return 176 * c.Else enqueue the DISCONNECT cmd 177 */ 178 wlan_vdev_mlme_ser_cancel_request(cmd->vdev, 179 WLAN_SER_CMD_NONSCAN, 180 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD); 181 182 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 183 mlme_err("Cmd already exist in the active queue"); 184 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 185 } 186 187 return wlan_serialization_request(cmd); 188 } 189 190 void 191 wlan_vdev_mlme_ser_remove_request(struct wlan_objmgr_vdev *vdev, 192 uint32_t cmd_id, 193 enum wlan_serialization_cmd_type cmd_type) 194 { 195 struct wlan_serialization_queued_cmd_info cmd = {0}; 196 197 mlme_debug("Remove the cmd type:%d", cmd_type); 198 199 cmd.vdev = vdev; 200 cmd.cmd_id = cmd_id; 201 cmd.cmd_type = cmd_type; 202 cmd.requestor = WLAN_UMAC_COMP_MLME; 203 cmd.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD; 204 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE; 205 206 /* Inform serialization for command completion */ 207 wlan_serialization_remove_cmd(&cmd); 208 } 209 210 void 211 wlan_vdev_mlme_ser_cancel_request(struct wlan_objmgr_vdev *vdev, 212 enum wlan_serialization_cmd_type cmd_type, 213 enum wlan_serialization_cancel_type req_type) 214 { 215 struct wlan_serialization_queued_cmd_info cmd = {0}; 216 217 cmd.vdev = vdev; 218 cmd.cmd_type = cmd_type; 219 cmd.req_type = req_type; 220 cmd.requestor = WLAN_UMAC_COMP_MLME; 221 cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE; 222 223 wlan_serialization_cancel_request(&cmd); 224 } 225 226 void 227 mlme_ser_inc_act_cmd_timeout(struct wlan_serialization_command *cmd) 228 { 229 mlme_debug("Increase timeout of cmd type:%d", cmd->cmd_type); 230 wlan_serialization_update_timer(cmd); 231 } 232