1 /* 2 * Copyright (c) 2019, 2021 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 #include "__osif_driver_sync.h" 20 #include "osif_driver_sync.h" 21 #include "qdf_lock.h" 22 #include "qdf_status.h" 23 #include "qdf_types.h" 24 #include "wlan_dsc_driver.h" 25 #include "wlan_dsc_psoc.h" 26 27 /** 28 * struct osif_driver_sync - a driver synchronization context 29 * @dsc_driver: the dsc_driver used for synchronization 30 * @in_use: indicates if the context is being used 31 * @is_registered: indicates if the context is registered for 32 * transitions/operations 33 */ 34 struct osif_driver_sync { 35 struct dsc_driver *dsc_driver; 36 bool in_use; 37 bool is_registered; 38 }; 39 40 static struct osif_driver_sync __osif_driver_sync; 41 static qdf_spinlock_t __osif_driver_sync_lock; 42 43 #define osif_driver_sync_lock_create() \ 44 qdf_spinlock_create(&__osif_driver_sync_lock) 45 #define osif_driver_sync_lock_destroy() \ 46 qdf_spinlock_destroy(&__osif_driver_sync_lock) 47 #define osif_driver_sync_lock() qdf_spin_lock_bh(&__osif_driver_sync_lock) 48 #define osif_driver_sync_unlock() qdf_spin_unlock_bh(&__osif_driver_sync_lock) 49 osif_driver_sync_lookup(void)50 static struct osif_driver_sync *osif_driver_sync_lookup(void) 51 { 52 if (!__osif_driver_sync.is_registered) 53 return NULL; 54 55 return &__osif_driver_sync; 56 } 57 osif_driver_sync_get(void)58 static struct osif_driver_sync *osif_driver_sync_get(void) 59 { 60 if (__osif_driver_sync.in_use) 61 return NULL; 62 63 __osif_driver_sync.in_use = true; 64 65 return &__osif_driver_sync; 66 } 67 osif_driver_sync_put(struct osif_driver_sync * driver_sync)68 static void osif_driver_sync_put(struct osif_driver_sync *driver_sync) 69 { 70 qdf_mem_zero(driver_sync, sizeof(*driver_sync)); 71 } 72 osif_driver_sync_create(struct osif_driver_sync ** out_driver_sync)73 int osif_driver_sync_create(struct osif_driver_sync **out_driver_sync) 74 { 75 QDF_STATUS status; 76 struct osif_driver_sync *driver_sync; 77 78 QDF_BUG(out_driver_sync); 79 if (!out_driver_sync) 80 return -EINVAL; 81 82 osif_driver_sync_lock(); 83 driver_sync = osif_driver_sync_get(); 84 osif_driver_sync_unlock(); 85 if (!driver_sync) 86 return -ENOMEM; 87 88 status = dsc_driver_create(&driver_sync->dsc_driver); 89 if (QDF_IS_STATUS_ERROR(status)) 90 goto sync_put; 91 92 *out_driver_sync = driver_sync; 93 94 return 0; 95 96 sync_put: 97 osif_driver_sync_lock(); 98 osif_driver_sync_put(driver_sync); 99 osif_driver_sync_unlock(); 100 101 return qdf_status_to_os_return(status); 102 } 103 104 int __osif_driver_sync_create_and_trans(struct osif_driver_sync ** out_driver_sync,const char * desc)105 __osif_driver_sync_create_and_trans(struct osif_driver_sync **out_driver_sync, 106 const char *desc) 107 { 108 struct osif_driver_sync *driver_sync; 109 QDF_STATUS status; 110 int errno; 111 112 errno = osif_driver_sync_create(&driver_sync); 113 if (errno) 114 return errno; 115 116 status = dsc_driver_trans_start(driver_sync->dsc_driver, desc); 117 if (QDF_IS_STATUS_ERROR(status)) 118 goto sync_destroy; 119 120 *out_driver_sync = driver_sync; 121 122 return 0; 123 124 sync_destroy: 125 osif_driver_sync_destroy(driver_sync); 126 127 return qdf_status_to_os_return(status); 128 } 129 osif_driver_sync_destroy(struct osif_driver_sync * driver_sync)130 void osif_driver_sync_destroy(struct osif_driver_sync *driver_sync) 131 { 132 QDF_BUG(driver_sync); 133 if (!driver_sync) 134 return; 135 136 dsc_driver_destroy(&driver_sync->dsc_driver); 137 138 osif_driver_sync_lock(); 139 osif_driver_sync_put(driver_sync); 140 osif_driver_sync_unlock(); 141 } 142 osif_driver_sync_register(struct osif_driver_sync * driver_sync)143 void osif_driver_sync_register(struct osif_driver_sync *driver_sync) 144 { 145 QDF_BUG(driver_sync); 146 if (!driver_sync) 147 return; 148 149 osif_driver_sync_lock(); 150 driver_sync->is_registered = true; 151 osif_driver_sync_unlock(); 152 } 153 osif_driver_sync_unregister(void)154 struct osif_driver_sync *osif_driver_sync_unregister(void) 155 { 156 struct osif_driver_sync *driver_sync; 157 158 osif_driver_sync_lock(); 159 driver_sync = osif_driver_sync_lookup(); 160 if (driver_sync) 161 driver_sync->is_registered = false; 162 osif_driver_sync_unlock(); 163 164 return driver_sync; 165 } 166 167 typedef QDF_STATUS (*driver_start_func)(struct dsc_driver *, const char *); 168 169 static int __osif_driver_sync_start_callback(struct osif_driver_sync ** out_driver_sync,const char * desc,driver_start_func driver_start_cb)170 __osif_driver_sync_start_callback(struct osif_driver_sync **out_driver_sync, 171 const char *desc, 172 driver_start_func driver_start_cb) 173 { 174 QDF_STATUS status; 175 struct osif_driver_sync *driver_sync; 176 177 *out_driver_sync = NULL; 178 179 driver_sync = osif_driver_sync_lookup(); 180 if (!driver_sync) 181 return -EAGAIN; 182 183 status = driver_start_cb(driver_sync->dsc_driver, desc); 184 if (QDF_IS_STATUS_ERROR(status)) 185 return qdf_status_to_os_return(status); 186 187 *out_driver_sync = driver_sync; 188 189 return 0; 190 } 191 192 static int __osif_driver_sync_start_wait_callback(struct osif_driver_sync ** out_driver_sync,const char * desc,driver_start_func driver_start_cb)193 __osif_driver_sync_start_wait_callback( 194 struct osif_driver_sync **out_driver_sync, 195 const char *desc, 196 driver_start_func driver_start_cb) 197 { 198 QDF_STATUS status; 199 struct osif_driver_sync *driver_sync; 200 201 *out_driver_sync = NULL; 202 203 osif_driver_sync_lock(); 204 driver_sync = osif_driver_sync_lookup(); 205 osif_driver_sync_unlock(); 206 if (!driver_sync) 207 return -EAGAIN; 208 209 status = driver_start_cb(driver_sync->dsc_driver, desc); 210 if (QDF_IS_STATUS_ERROR(status)) 211 return qdf_status_to_os_return(status); 212 213 *out_driver_sync = driver_sync; 214 215 return 0; 216 } __osif_driver_sync_trans_start(struct osif_driver_sync ** out_driver_sync,const char * desc)217 int __osif_driver_sync_trans_start(struct osif_driver_sync **out_driver_sync, 218 const char *desc) 219 { 220 int errno; 221 222 osif_driver_sync_lock(); 223 errno = __osif_driver_sync_start_callback(out_driver_sync, desc, 224 dsc_driver_trans_start); 225 osif_driver_sync_unlock(); 226 227 return errno; 228 } 229 230 int __osif_driver_sync_trans_start_wait(struct osif_driver_sync ** out_driver_sync,const char * desc)231 __osif_driver_sync_trans_start_wait(struct osif_driver_sync **out_driver_sync, 232 const char *desc) 233 { 234 int errno; 235 236 /* since dsc_driver_trans_start_wait may sleep do not take lock here */ 237 errno = __osif_driver_sync_start_wait_callback(out_driver_sync, desc, 238 dsc_driver_trans_start_wait); 239 240 return errno; 241 } 242 osif_driver_sync_trans_stop(struct osif_driver_sync * driver_sync)243 void osif_driver_sync_trans_stop(struct osif_driver_sync *driver_sync) 244 { 245 dsc_driver_trans_stop(driver_sync->dsc_driver); 246 } 247 osif_driver_sync_assert_trans_protected(void)248 void osif_driver_sync_assert_trans_protected(void) 249 { 250 struct osif_driver_sync *driver_sync; 251 252 osif_driver_sync_lock(); 253 254 driver_sync = osif_driver_sync_lookup(); 255 QDF_BUG(driver_sync); 256 if (driver_sync) 257 dsc_driver_assert_trans_protected(driver_sync->dsc_driver); 258 259 osif_driver_sync_unlock(); 260 } 261 __osif_driver_sync_op_start(struct osif_driver_sync ** out_driver_sync,const char * func)262 int __osif_driver_sync_op_start(struct osif_driver_sync **out_driver_sync, 263 const char *func) 264 { 265 int errno; 266 267 osif_driver_sync_lock(); 268 errno = __osif_driver_sync_start_callback(out_driver_sync, func, 269 _dsc_driver_op_start); 270 osif_driver_sync_unlock(); 271 272 return errno; 273 } 274 __osif_driver_sync_op_stop(struct osif_driver_sync * driver_sync,const char * func)275 void __osif_driver_sync_op_stop(struct osif_driver_sync *driver_sync, 276 const char *func) 277 { 278 _dsc_driver_op_stop(driver_sync->dsc_driver, func); 279 } 280 osif_driver_sync_wait_for_ops(struct osif_driver_sync * driver_sync)281 void osif_driver_sync_wait_for_ops(struct osif_driver_sync *driver_sync) 282 { 283 dsc_driver_wait_for_ops(driver_sync->dsc_driver); 284 } 285 osif_driver_sync_init(void)286 void osif_driver_sync_init(void) 287 { 288 osif_driver_sync_lock_create(); 289 } 290 osif_driver_sync_deinit(void)291 void osif_driver_sync_deinit(void) 292 { 293 osif_driver_sync_lock_destroy(); 294 } 295 296 static QDF_STATUS __osif_driver_sync_dsc_psoc_create(struct dsc_psoc ** out_dsc_psoc)297 __osif_driver_sync_dsc_psoc_create(struct dsc_psoc **out_dsc_psoc) 298 { 299 struct osif_driver_sync *driver_sync; 300 301 driver_sync = osif_driver_sync_lookup(); 302 if (!driver_sync) 303 return QDF_STATUS_E_INVAL; 304 305 return dsc_psoc_create(driver_sync->dsc_driver, out_dsc_psoc); 306 } 307 osif_driver_sync_dsc_psoc_create(struct dsc_psoc ** out_dsc_psoc)308 QDF_STATUS osif_driver_sync_dsc_psoc_create(struct dsc_psoc **out_dsc_psoc) 309 { 310 QDF_STATUS status; 311 312 osif_driver_sync_lock(); 313 status = __osif_driver_sync_dsc_psoc_create(out_dsc_psoc); 314 osif_driver_sync_unlock(); 315 316 return status; 317 } 318 319