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 * DOC: wlan_cp_stats_comp_handler.c 21 * 22 * This file maintain definitions to APIs which handle attach/detach of other 23 * UMAC component specific cp stat object to cp stats 24 * 25 * Components calling configure API should alloc data structure while attaching 26 * dealloc while detaching, where as address for which to be deallocated will 27 * be passed back to component for data 28 */ 29 #include "wlan_cp_stats_comp_handler.h" 30 #include "wlan_cp_stats_defs.h" 31 #include <wlan_cp_stats_ucfg_api.h> 32 #include <wlan_cp_stats_utils_api.h> 33 34 static QDF_STATUS 35 wlan_cp_stats_psoc_comp_obj_config 36 (struct wlan_objmgr_psoc *psoc, enum wlan_cp_stats_comp_id comp_id, 37 enum wlan_cp_stats_cfg_state cfg_state, void *data) 38 { 39 struct psoc_cp_stats *psoc_cs; 40 41 psoc_cs = wlan_cp_stats_get_psoc_stats_obj(psoc); 42 if (!psoc_cs) { 43 cp_stats_err("psoc cp stats object is null"); 44 return QDF_STATUS_E_INVAL; 45 } 46 47 wlan_cp_stats_psoc_obj_lock(psoc_cs); 48 if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) { 49 if (psoc_cs->psoc_comp_priv_obj[comp_id]) { 50 wlan_cp_stats_psoc_obj_unlock(psoc_cs); 51 return QDF_STATUS_E_EXISTS; 52 } 53 psoc_cs->psoc_comp_priv_obj[comp_id] = data; 54 } else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) { 55 if (psoc_cs->psoc_comp_priv_obj[comp_id] != data) { 56 wlan_cp_stats_psoc_obj_unlock(psoc_cs); 57 return QDF_STATUS_E_INVAL; 58 } 59 data = psoc_cs->psoc_comp_priv_obj[comp_id]; 60 psoc_cs->psoc_comp_priv_obj[comp_id] = NULL; 61 } else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) { 62 cp_stats_err("Invalid cp stats cfg_state"); 63 wlan_cp_stats_psoc_obj_unlock(psoc_cs); 64 return QDF_STATUS_E_INVAL; 65 } 66 67 wlan_cp_stats_psoc_obj_unlock(psoc_cs); 68 return QDF_STATUS_SUCCESS; 69 } 70 71 static QDF_STATUS 72 wlan_cp_stats_pdev_comp_obj_config 73 (struct wlan_objmgr_pdev *pdev, enum wlan_cp_stats_comp_id comp_id, 74 enum wlan_cp_stats_cfg_state cfg_state, void *data) 75 { 76 struct pdev_cp_stats *pdev_cs; 77 78 pdev_cs = wlan_cp_stats_get_pdev_stats_obj(pdev); 79 if (!pdev_cs) { 80 cp_stats_err("pdev cp stats object is null"); 81 return QDF_STATUS_E_INVAL; 82 } 83 84 wlan_cp_stats_pdev_obj_lock(pdev_cs); 85 if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) { 86 if (pdev_cs->pdev_comp_priv_obj[comp_id]) { 87 wlan_cp_stats_pdev_obj_unlock(pdev_cs); 88 return QDF_STATUS_E_EXISTS; 89 } 90 pdev_cs->pdev_comp_priv_obj[comp_id] = data; 91 } else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) { 92 if (pdev_cs->pdev_comp_priv_obj[comp_id] != data) { 93 wlan_cp_stats_pdev_obj_unlock(pdev_cs); 94 return QDF_STATUS_E_INVAL; 95 } 96 data = pdev_cs->pdev_comp_priv_obj[comp_id]; 97 pdev_cs->pdev_comp_priv_obj[comp_id] = NULL; 98 } else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) { 99 cp_stats_err("Invalid cp stats cfg_state"); 100 wlan_cp_stats_pdev_obj_unlock(pdev_cs); 101 return QDF_STATUS_E_INVAL; 102 } 103 104 wlan_cp_stats_pdev_obj_unlock(pdev_cs); 105 return QDF_STATUS_SUCCESS; 106 } 107 108 static QDF_STATUS 109 wlan_cp_stats_vdev_comp_obj_config 110 (struct wlan_objmgr_vdev *vdev, enum wlan_cp_stats_comp_id comp_id, 111 enum wlan_cp_stats_cfg_state cfg_state, void *data) 112 { 113 struct vdev_cp_stats *vdev_cs; 114 115 vdev_cs = wlan_cp_stats_get_vdev_stats_obj(vdev); 116 if (!vdev_cs) { 117 cp_stats_err("vdev cp stats object is null"); 118 return QDF_STATUS_E_INVAL; 119 } 120 121 wlan_cp_stats_vdev_obj_lock(vdev_cs); 122 if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) { 123 if (vdev_cs->vdev_comp_priv_obj[comp_id]) { 124 wlan_cp_stats_vdev_obj_unlock(vdev_cs); 125 return QDF_STATUS_E_EXISTS; 126 } 127 vdev_cs->vdev_comp_priv_obj[comp_id] = data; 128 } else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) { 129 if (vdev_cs->vdev_comp_priv_obj[comp_id] != data) { 130 wlan_cp_stats_vdev_obj_unlock(vdev_cs); 131 return QDF_STATUS_E_INVAL; 132 } 133 data = vdev_cs->vdev_comp_priv_obj[comp_id]; 134 vdev_cs->vdev_comp_priv_obj[comp_id] = NULL; 135 } else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) { 136 cp_stats_err("Invalid cp stats cfg_state"); 137 wlan_cp_stats_vdev_obj_unlock(vdev_cs); 138 return QDF_STATUS_E_INVAL; 139 } 140 141 wlan_cp_stats_vdev_obj_unlock(vdev_cs); 142 return QDF_STATUS_SUCCESS; 143 } 144 145 static QDF_STATUS 146 wlan_cp_stats_peer_comp_obj_config 147 (struct wlan_objmgr_peer *peer, enum wlan_cp_stats_comp_id comp_id, 148 enum wlan_cp_stats_cfg_state cfg_state, void *data) 149 { 150 struct peer_cp_stats *peer_cs; 151 152 peer_cs = wlan_cp_stats_get_peer_stats_obj(peer); 153 if (!peer_cs) { 154 cp_stats_err("peer cp stats object is null"); 155 return QDF_STATUS_E_INVAL; 156 } 157 158 wlan_cp_stats_peer_obj_lock(peer_cs); 159 if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) { 160 if (peer_cs->peer_comp_priv_obj[comp_id]) { 161 wlan_cp_stats_peer_obj_unlock(peer_cs); 162 return QDF_STATUS_E_EXISTS; 163 } 164 peer_cs->peer_comp_priv_obj[comp_id] = data; 165 } else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) { 166 if (peer_cs->peer_comp_priv_obj[comp_id] != data) { 167 wlan_cp_stats_peer_obj_unlock(peer_cs); 168 return QDF_STATUS_E_INVAL; 169 } 170 data = peer_cs->peer_comp_priv_obj[comp_id]; 171 peer_cs->peer_comp_priv_obj[comp_id] = NULL; 172 } else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) { 173 cp_stats_err("Invalid cp stats cfg_state"); 174 wlan_cp_stats_peer_obj_unlock(peer_cs); 175 return QDF_STATUS_E_INVAL; 176 } 177 178 wlan_cp_stats_peer_obj_unlock(peer_cs); 179 return QDF_STATUS_SUCCESS; 180 } 181 182 QDF_STATUS 183 wlan_cp_stats_comp_obj_config(enum wlan_objmgr_obj_type obj_type, 184 enum wlan_cp_stats_cfg_state cfg_state, 185 enum wlan_cp_stats_comp_id comp_id, 186 void *cmn_obj, void *data) 187 { 188 QDF_STATUS status; 189 190 if (!cmn_obj) { 191 cp_stats_err("Common object is NULL"); 192 return QDF_STATUS_E_INVAL; 193 } 194 195 /* component id is invalid */ 196 if (comp_id >= WLAN_CP_STATS_MAX_COMPONENTS) { 197 cp_stats_err("Invalid component Id"); 198 return QDF_STATUS_MAXCOMP_FAIL; 199 } 200 201 switch (obj_type) { 202 case WLAN_PSOC_OP: 203 status = 204 wlan_cp_stats_psoc_comp_obj_config( 205 (struct wlan_objmgr_psoc *)cmn_obj, 206 comp_id, cfg_state, data); 207 break; 208 case WLAN_PDEV_OP: 209 status = 210 wlan_cp_stats_pdev_comp_obj_config( 211 (struct wlan_objmgr_pdev *)cmn_obj, 212 comp_id, cfg_state, data); 213 break; 214 case WLAN_VDEV_OP: 215 status = 216 wlan_cp_stats_vdev_comp_obj_config( 217 (struct wlan_objmgr_vdev *)cmn_obj, 218 comp_id, cfg_state, data); 219 break; 220 case WLAN_PEER_OP: 221 status = 222 wlan_cp_stats_peer_comp_obj_config( 223 (struct wlan_objmgr_peer *)cmn_obj, 224 comp_id, cfg_state, data); 225 break; 226 default: 227 cp_stats_err("Invalid common object"); 228 return QDF_STATUS_E_INVAL; 229 } 230 231 return status; 232 } 233