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