1 /* 2 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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 * DOC: wlan_twt_api.c 20 * This file defines the APIs of TWT component. 21 */ 22 #include <wlan_twt_api.h> 23 #include "twt/core/src/wlan_twt_objmgr_handler.h" 24 #include "twt/core/src/wlan_twt_common.h" 25 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD 26 #include <wlan_pmo_obj_mgmt_api.h> 27 #endif 28 29 struct wlan_lmac_if_twt_tx_ops * 30 wlan_twt_get_tx_ops(struct wlan_objmgr_psoc *psoc) 31 { 32 struct wlan_lmac_if_tx_ops *tx_ops; 33 34 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 35 if (!tx_ops) { 36 twt_err("tx_ops is NULL"); 37 return NULL; 38 } 39 40 return &tx_ops->twt_tx_ops; 41 } 42 43 struct wlan_lmac_if_twt_rx_ops * 44 wlan_twt_get_rx_ops(struct wlan_objmgr_psoc *psoc) 45 { 46 struct wlan_lmac_if_rx_ops *rx_ops; 47 48 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 49 if (!rx_ops) { 50 twt_err("rx_ops is NULL"); 51 return NULL; 52 } 53 54 return &rx_ops->twt_rx_ops; 55 } 56 57 struct twt_psoc_priv_obj* 58 wlan_twt_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc) 59 { 60 struct twt_psoc_priv_obj *twt_psoc; 61 62 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 63 WLAN_UMAC_COMP_TWT); 64 if (!twt_psoc) { 65 twt_err("TWT PSOC component object is NULL"); 66 return NULL; 67 } 68 69 return twt_psoc; 70 } 71 72 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD 73 static QDF_STATUS 74 wlan_twt_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg) 75 { 76 wlan_twt_psoc_set_pmo_disable(psoc, REASON_PMO_SUSPEND); 77 return QDF_STATUS_SUCCESS; 78 } 79 80 static QDF_STATUS 81 wlan_twt_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg) 82 { 83 wlan_twt_psoc_set_pmo_enable(psoc, REASON_PMO_SUSPEND); 84 return QDF_STATUS_SUCCESS; 85 } 86 87 static void 88 wlan_twt_register_pmo_handler(void) 89 { 90 pmo_register_suspend_handler(WLAN_UMAC_COMP_TWT, 91 wlan_twt_suspend_handler, NULL); 92 pmo_register_resume_handler(WLAN_UMAC_COMP_TWT, 93 wlan_twt_resume_handler, NULL); 94 } 95 96 static inline void 97 wlan_twt_unregister_pmo_handler(void) 98 { 99 pmo_unregister_suspend_handler(WLAN_UMAC_COMP_TWT, 100 wlan_twt_suspend_handler); 101 pmo_unregister_resume_handler(WLAN_UMAC_COMP_TWT, 102 wlan_twt_resume_handler); 103 } 104 105 #else 106 static void 107 wlan_twt_register_pmo_handler(void) 108 { 109 } 110 111 static inline void 112 wlan_twt_unregister_pmo_handler(void) 113 { 114 } 115 116 #endif 117 118 QDF_STATUS wlan_twt_init(void) 119 { 120 QDF_STATUS status = QDF_STATUS_E_FAILURE; 121 122 status = wlan_objmgr_register_psoc_create_handler 123 (WLAN_UMAC_COMP_TWT, 124 wlan_twt_psoc_obj_create_handler, 125 NULL); 126 if (QDF_IS_STATUS_ERROR(status)) { 127 twt_err("Failed to register psoc create handler"); 128 goto wlan_twt_psoc_init_fail1; 129 } 130 131 status = wlan_objmgr_register_psoc_destroy_handler 132 (WLAN_UMAC_COMP_TWT, 133 wlan_twt_psoc_obj_destroy_handler, 134 NULL); 135 if (QDF_IS_STATUS_ERROR(status)) { 136 twt_err("Failed to register psoc destroy handler"); 137 goto wlan_twt_psoc_init_fail2; 138 } 139 140 status = wlan_objmgr_register_vdev_create_handler 141 (WLAN_UMAC_COMP_TWT, 142 wlan_twt_vdev_obj_create_handler, 143 NULL); 144 if (QDF_IS_STATUS_ERROR(status)) { 145 twt_err("Failed to register vdev create handler"); 146 goto wlan_twt_vdev_init_fail1; 147 } 148 149 status = wlan_objmgr_register_vdev_destroy_handler 150 (WLAN_UMAC_COMP_TWT, 151 wlan_twt_vdev_obj_destroy_handler, 152 NULL); 153 if (QDF_IS_STATUS_ERROR(status)) { 154 twt_err("Failed to register vdev destroy handler"); 155 goto wlan_twt_vdev_init_fail2; 156 } 157 158 status = wlan_objmgr_register_peer_create_handler 159 (WLAN_UMAC_COMP_TWT, 160 wlan_twt_peer_obj_create_handler, 161 NULL); 162 if (QDF_IS_STATUS_ERROR(status)) { 163 twt_err("Failed to register peer create handler"); 164 goto wlan_twt_peer_init_fail1; 165 } 166 167 status = wlan_objmgr_register_peer_destroy_handler 168 (WLAN_UMAC_COMP_TWT, 169 wlan_twt_peer_obj_destroy_handler, 170 NULL); 171 if (QDF_IS_STATUS_ERROR(status)) { 172 twt_err("Failed to register peer destroy handler"); 173 goto wlan_twt_peer_init_fail2; 174 } 175 176 return QDF_STATUS_SUCCESS; 177 178 wlan_twt_peer_init_fail2: 179 wlan_objmgr_unregister_peer_create_handler 180 (WLAN_UMAC_COMP_TWT, 181 wlan_twt_peer_obj_create_handler, 182 NULL); 183 wlan_twt_peer_init_fail1: 184 wlan_objmgr_unregister_vdev_destroy_handler 185 (WLAN_UMAC_COMP_TWT, 186 wlan_twt_vdev_obj_destroy_handler, 187 NULL); 188 wlan_twt_vdev_init_fail2: 189 wlan_objmgr_unregister_vdev_create_handler 190 (WLAN_UMAC_COMP_TWT, 191 wlan_twt_vdev_obj_create_handler, 192 NULL); 193 wlan_twt_vdev_init_fail1: 194 wlan_objmgr_unregister_psoc_destroy_handler 195 (WLAN_UMAC_COMP_TWT, 196 wlan_twt_psoc_obj_destroy_handler, 197 NULL); 198 wlan_twt_psoc_init_fail2: 199 wlan_objmgr_unregister_psoc_create_handler 200 (WLAN_UMAC_COMP_TWT, 201 wlan_twt_psoc_obj_create_handler, 202 NULL); 203 wlan_twt_psoc_init_fail1: 204 return status; 205 } 206 207 QDF_STATUS wlan_twt_deinit(void) 208 { 209 QDF_STATUS status = QDF_STATUS_E_FAILURE; 210 211 status = wlan_objmgr_unregister_psoc_create_handler 212 (WLAN_UMAC_COMP_TWT, 213 wlan_twt_psoc_obj_create_handler, 214 NULL); 215 if (QDF_IS_STATUS_ERROR(status)) 216 twt_err("Failed to unregister psoc create handler"); 217 218 status = wlan_objmgr_unregister_psoc_destroy_handler 219 (WLAN_UMAC_COMP_TWT, 220 wlan_twt_psoc_obj_destroy_handler, 221 NULL); 222 if (QDF_IS_STATUS_ERROR(status)) 223 twt_err("Failed to unregister psoc destroy handler"); 224 225 status = wlan_objmgr_unregister_vdev_create_handler 226 (WLAN_UMAC_COMP_TWT, 227 wlan_twt_vdev_obj_create_handler, 228 NULL); 229 if (QDF_IS_STATUS_ERROR(status)) 230 twt_err("Failed to unregister vdev create handler"); 231 232 status = wlan_objmgr_unregister_vdev_destroy_handler 233 (WLAN_UMAC_COMP_TWT, 234 wlan_twt_vdev_obj_destroy_handler, 235 NULL); 236 if (QDF_IS_STATUS_ERROR(status)) 237 twt_err("Failed to unregister vdev destroy handler"); 238 239 status = wlan_objmgr_unregister_peer_create_handler 240 (WLAN_UMAC_COMP_TWT, 241 wlan_twt_peer_obj_create_handler, 242 NULL); 243 if (QDF_IS_STATUS_ERROR(status)) 244 twt_err("Failed to unregister peer create handler"); 245 246 status = wlan_objmgr_unregister_peer_destroy_handler 247 (WLAN_UMAC_COMP_TWT, 248 wlan_twt_peer_obj_destroy_handler, 249 NULL); 250 if (QDF_IS_STATUS_ERROR(status)) 251 twt_err("Failed to unregister peer destroy handler"); 252 253 return status; 254 } 255 256 QDF_STATUS twt_psoc_enable(struct wlan_objmgr_psoc *psoc) 257 { 258 QDF_STATUS status = QDF_STATUS_E_NULL_VALUE; 259 struct wlan_lmac_if_twt_tx_ops *tx_ops; 260 261 tx_ops = wlan_twt_get_tx_ops(psoc); 262 if (!tx_ops || !tx_ops->register_events) { 263 twt_err("%s is null", !tx_ops ? "tx_ops" : "register_events"); 264 return QDF_STATUS_E_NULL_VALUE; 265 } 266 267 status = tx_ops->register_events(psoc); 268 if (QDF_IS_STATUS_ERROR(status)) 269 twt_err("twt_register_events failed (status=%d)", status); 270 271 wlan_twt_register_pmo_handler(); 272 273 return status; 274 } 275 276 QDF_STATUS twt_psoc_disable(struct wlan_objmgr_psoc *psoc) 277 { 278 QDF_STATUS status = QDF_STATUS_E_NULL_VALUE; 279 struct wlan_lmac_if_twt_tx_ops *tx_ops; 280 281 tx_ops = wlan_twt_get_tx_ops(psoc); 282 if (!tx_ops || !tx_ops->deregister_events) { 283 twt_err("%s is null", !tx_ops ? "tx_ops" : "deregister_events"); 284 return QDF_STATUS_E_NULL_VALUE; 285 } 286 287 status = tx_ops->deregister_events(psoc); 288 if (QDF_IS_STATUS_ERROR(status)) 289 twt_err("twt_deregister_events failed (status=%d)", 290 status); 291 292 wlan_twt_unregister_pmo_handler(); 293 294 return status; 295 } 296 297 QDF_STATUS 298 wlan_set_peer_twt_capabilities(struct wlan_objmgr_psoc *psoc, 299 struct qdf_mac_addr *peer_mac, 300 uint8_t peer_cap) 301 { 302 return wlan_twt_set_peer_capabilities(psoc, peer_mac, peer_cap); 303 } 304 305