1 /* 2 * Copyright (c) 2018-2019 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 * @file wlan_vdev_mlme_ser.c 19 * This file contains the APIs to support interface between vdev_mlme and 20 * serialization module 21 */ 22 23 #include <qdf_types.h> 24 #include <qdf_status.h> 25 #include <qdf_mem.h> 26 #include <wlan_serialization_api.h> 27 #include <wlan_objmgr_vdev_obj.h> 28 #include <wlan_cmn.h> 29 #include <wlan_mlme_dbg.h> 30 #include <include/wlan_mlme_cmn.h> 31 #include <wlan_vdev_mlme_api.h> 32 #include <wlan_vdev_mlme_ser_if.h> 33 34 enum wlan_serialization_status 35 wlan_vdev_mlme_ser_start_bss(struct wlan_serialization_command *cmd) 36 { 37 struct vdev_mlme_obj *vdev_mlme; 38 39 if (!cmd || !cmd->vdev) { 40 mlme_err("Null input"); 41 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 42 } 43 44 /* 45 * Serialization command filtering logic 46 * a. Cancel any existing start bss cmd in the pending queue 47 * b. If there is an start bss cmd in active queue and 48 * there is no stop bss cmd in pending queue, 49 * then explicitly enqueue a stop bss cmd to avoid back to 50 * back execution of UP cmd. 51 * c. Enqueue the new start bss cmd with serialization 52 */ 53 wlan_vdev_mlme_ser_cancel_request( 54 cmd->vdev, 55 WLAN_SER_CMD_VDEV_START_BSS, 56 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); 57 58 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 59 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(cmd->vdev); 60 if (mlme_vdev_enqueue_exp_ser_cmd(vdev_mlme, 61 WLAN_SER_CMD_VDEV_STOP_BSS)) { 62 mlme_err("Unable to add the exception cmd request"); 63 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 64 } 65 } 66 67 return wlan_serialization_request(cmd); 68 } 69 70 enum wlan_serialization_status 71 wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd) 72 { 73 uint8_t stop_cmd_pending; 74 uint8_t ret; 75 76 if (!cmd || !cmd->vdev) { 77 mlme_err("Null input"); 78 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 79 } 80 /* 81 * Serialization command filtering logic 82 * a. Cancel any existing start/stop/restart command in the pending 83 * queue. 84 * b. If there is a stop cmd in active queue then return 85 * c. Else enqueue the cmd 86 * d. If stop cmd already existed in pending queue then return with 87 * already exists else return the enqueued return value. 88 */ 89 stop_cmd_pending = 90 wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd); 91 wlan_vdev_mlme_ser_cancel_request(cmd->vdev, 92 WLAN_SER_CMD_NONSCAN, 93 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD); 94 95 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 96 mlme_debug("Cmd already exist in the active queue"); 97 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 98 } 99 100 ret = wlan_serialization_request(cmd); 101 102 if (stop_cmd_pending && ret == WLAN_SER_CMD_PENDING) 103 return WLAN_SER_CMD_ALREADY_EXISTS; 104 else 105 return ret; 106 } 107 108 enum wlan_serialization_status 109 wlan_vdev_mlme_ser_restart_bss(struct wlan_serialization_command *cmd) 110 { 111 if (!cmd || !cmd->vdev) { 112 mlme_err("Null input"); 113 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 114 } 115 /* 116 * Serialization command filtering logic 117 * a. Cancel any existing RESTART cmd in the pending queue 118 * b. Enqueue the new RESTART cmd 119 */ 120 wlan_vdev_mlme_ser_cancel_request( 121 cmd->vdev, 122 WLAN_SER_CMD_VDEV_RESTART, 123 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); 124 return wlan_serialization_request(cmd); 125 } 126 127 enum wlan_serialization_status 128 wlan_vdev_mlme_ser_connect(struct wlan_serialization_command *cmd) 129 { 130 struct vdev_mlme_obj *vdev_mlme; 131 132 if (!cmd || !cmd->vdev) { 133 mlme_err("Null input"); 134 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 135 } 136 /* 137 * Serialization command filtering logic 138 * a. Cancel any existing CONNECT cmd in the pending queue 139 * b. If there is an CONNECT cmd in active queue and there is no 140 * DISCONNECT cmd in pending queue, then explicitly enqueue a 141 * DISCONNECT cmd to avoid back to back execution of CONNECT cmd. 142 * c. Enqueue the new CONNECT cmd to the pending queue 143 */ 144 wlan_vdev_mlme_ser_cancel_request( 145 cmd->vdev, 146 WLAN_SER_CMD_VDEV_CONNECT, 147 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); 148 149 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 150 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(cmd->vdev); 151 if (mlme_vdev_enqueue_exp_ser_cmd(vdev_mlme, 152 WLAN_SER_CMD_VDEV_DISCONNECT)) { 153 mlme_err("Unable to add the exception cmd request"); 154 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 155 } 156 } 157 158 return wlan_serialization_request(cmd); 159 } 160 161 enum wlan_serialization_status 162 wlan_vdev_mlme_ser_disconnect(struct wlan_serialization_command *cmd) 163 { 164 if (!cmd || !cmd->vdev) { 165 mlme_err("Null input"); 166 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 167 } 168 /* 169 * Serialization command filtering logic 170 * a.Cancel any existing CONNECT/DISCONNECT/RESTART command in the 171 * pending queue 172 * b.If there is a DISCONNECT cmd in active queue then return 173 * c.Else enqueue the DISCONNECT cmd 174 */ 175 wlan_vdev_mlme_ser_cancel_request(cmd->vdev, 176 WLAN_SER_CMD_NONSCAN, 177 WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD); 178 179 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { 180 mlme_debug("Cmd already exist in the active queue"); 181 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 182 } 183 184 return wlan_serialization_request(cmd); 185 } 186 187 void 188 wlan_vdev_mlme_ser_remove_request(struct wlan_objmgr_vdev *vdev, 189 uint32_t cmd_id, 190 enum wlan_serialization_cmd_type cmd_type) 191 { 192 struct wlan_serialization_queued_cmd_info cmd = {0}; 193 194 mlme_debug("Remove the cmd type:%d", cmd_type); 195 196 cmd.vdev = vdev; 197 cmd.cmd_id = cmd_id; 198 cmd.cmd_type = cmd_type; 199 cmd.requestor = WLAN_UMAC_COMP_MLME; 200 cmd.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD; 201 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE; 202 203 /* Inform serialization for command completion */ 204 wlan_serialization_remove_cmd(&cmd); 205 } 206 207 void 208 wlan_vdev_mlme_ser_cancel_request(struct wlan_objmgr_vdev *vdev, 209 enum wlan_serialization_cmd_type cmd_type, 210 enum wlan_serialization_cancel_type req_type) 211 { 212 struct wlan_serialization_queued_cmd_info cmd = {0}; 213 214 cmd.vdev = vdev; 215 cmd.cmd_type = cmd_type; 216 cmd.req_type = req_type; 217 cmd.requestor = WLAN_UMAC_COMP_MLME; 218 cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE; 219 220 wlan_serialization_cancel_request(&cmd); 221 } 222 223 void 224 mlme_ser_inc_act_cmd_timeout(struct wlan_serialization_command *cmd) 225 { 226 mlme_debug("Increase timeout of cmd type:%d", cmd->cmd_type); 227 wlan_serialization_update_timer(cmd); 228 } 229