| rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 
|  | 2 | /* | 
|  | 3 | * Portions of this file | 
|  | 4 | * Copyright(c) 2016 Intel Deutschland GmbH | 
|  | 5 | */ | 
|  | 6 |  | 
|  | 7 | #ifndef __MAC80211_DRIVER_OPS | 
|  | 8 | #define __MAC80211_DRIVER_OPS | 
|  | 9 |  | 
|  | 10 | #include <net/mac80211.h> | 
|  | 11 | #include "ieee80211_i.h" | 
|  | 12 | #include "trace.h" | 
|  | 13 |  | 
|  | 14 | static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | 
|  | 15 | { | 
|  | 16 | return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), | 
|  | 17 | "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n", | 
|  | 18 | sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); | 
|  | 19 | } | 
|  | 20 |  | 
|  | 21 | static inline struct ieee80211_sub_if_data * | 
|  | 22 | get_bss_sdata(struct ieee80211_sub_if_data *sdata) | 
|  | 23 | { | 
|  | 24 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 
|  | 25 | sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, | 
|  | 26 | u.ap); | 
|  | 27 |  | 
|  | 28 | return sdata; | 
|  | 29 | } | 
|  | 30 |  | 
|  | 31 | static inline void drv_tx(struct ieee80211_local *local, | 
|  | 32 | struct ieee80211_tx_control *control, | 
|  | 33 | struct sk_buff *skb) | 
|  | 34 | { | 
|  | 35 | local->ops->tx(&local->hw, control, skb); | 
|  | 36 | } | 
|  | 37 |  | 
|  | 38 | static inline void drv_sync_rx_queues(struct ieee80211_local *local, | 
|  | 39 | struct sta_info *sta) | 
|  | 40 | { | 
|  | 41 | if (local->ops->sync_rx_queues) { | 
|  | 42 | trace_drv_sync_rx_queues(local, sta->sdata, &sta->sta); | 
|  | 43 | local->ops->sync_rx_queues(&local->hw); | 
|  | 44 | trace_drv_return_void(local); | 
|  | 45 | } | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, | 
|  | 49 | u32 sset, u8 *data) | 
|  | 50 | { | 
|  | 51 | struct ieee80211_local *local = sdata->local; | 
|  | 52 | if (local->ops->get_et_strings) { | 
|  | 53 | trace_drv_get_et_strings(local, sset); | 
|  | 54 | local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data); | 
|  | 55 | trace_drv_return_void(local); | 
|  | 56 | } | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata, | 
|  | 60 | struct ethtool_stats *stats, | 
|  | 61 | u64 *data) | 
|  | 62 | { | 
|  | 63 | struct ieee80211_local *local = sdata->local; | 
|  | 64 | if (local->ops->get_et_stats) { | 
|  | 65 | trace_drv_get_et_stats(local); | 
|  | 66 | local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data); | 
|  | 67 | trace_drv_return_void(local); | 
|  | 68 | } | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata, | 
|  | 72 | int sset) | 
|  | 73 | { | 
|  | 74 | struct ieee80211_local *local = sdata->local; | 
|  | 75 | int rv = 0; | 
|  | 76 | if (local->ops->get_et_sset_count) { | 
|  | 77 | trace_drv_get_et_sset_count(local, sset); | 
|  | 78 | rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif, | 
|  | 79 | sset); | 
|  | 80 | trace_drv_return_int(local, rv); | 
|  | 81 | } | 
|  | 82 | return rv; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | int drv_start(struct ieee80211_local *local); | 
|  | 86 | void drv_stop(struct ieee80211_local *local); | 
|  | 87 |  | 
|  | 88 | #ifdef CONFIG_PM | 
|  | 89 | static inline int drv_suspend(struct ieee80211_local *local, | 
|  | 90 | struct cfg80211_wowlan *wowlan) | 
|  | 91 | { | 
|  | 92 | int ret; | 
|  | 93 |  | 
|  | 94 | might_sleep(); | 
|  | 95 |  | 
|  | 96 | trace_drv_suspend(local); | 
|  | 97 | ret = local->ops->suspend(&local->hw, wowlan); | 
|  | 98 | trace_drv_return_int(local, ret); | 
|  | 99 | return ret; | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | static inline int drv_resume(struct ieee80211_local *local) | 
|  | 103 | { | 
|  | 104 | int ret; | 
|  | 105 |  | 
|  | 106 | might_sleep(); | 
|  | 107 |  | 
|  | 108 | trace_drv_resume(local); | 
|  | 109 | ret = local->ops->resume(&local->hw); | 
|  | 110 | trace_drv_return_int(local, ret); | 
|  | 111 | return ret; | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | static inline void drv_set_wakeup(struct ieee80211_local *local, | 
|  | 115 | bool enabled) | 
|  | 116 | { | 
|  | 117 | might_sleep(); | 
|  | 118 |  | 
|  | 119 | if (!local->ops->set_wakeup) | 
|  | 120 | return; | 
|  | 121 |  | 
|  | 122 | trace_drv_set_wakeup(local, enabled); | 
|  | 123 | local->ops->set_wakeup(&local->hw, enabled); | 
|  | 124 | trace_drv_return_void(local); | 
|  | 125 | } | 
|  | 126 | #endif | 
|  | 127 |  | 
|  | 128 | int drv_add_interface(struct ieee80211_local *local, | 
|  | 129 | struct ieee80211_sub_if_data *sdata); | 
|  | 130 |  | 
|  | 131 | int drv_change_interface(struct ieee80211_local *local, | 
|  | 132 | struct ieee80211_sub_if_data *sdata, | 
|  | 133 | enum nl80211_iftype type, bool p2p); | 
|  | 134 |  | 
|  | 135 | void drv_remove_interface(struct ieee80211_local *local, | 
|  | 136 | struct ieee80211_sub_if_data *sdata); | 
|  | 137 |  | 
|  | 138 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 
|  | 139 | { | 
|  | 140 | int ret; | 
|  | 141 |  | 
|  | 142 | might_sleep(); | 
|  | 143 |  | 
|  | 144 | trace_drv_config(local, changed); | 
|  | 145 | ret = local->ops->config(&local->hw, changed); | 
|  | 146 | trace_drv_return_int(local, ret); | 
|  | 147 | return ret; | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | static inline void drv_bss_info_changed(struct ieee80211_local *local, | 
|  | 151 | struct ieee80211_sub_if_data *sdata, | 
|  | 152 | struct ieee80211_bss_conf *info, | 
|  | 153 | u32 changed) | 
|  | 154 | { | 
|  | 155 | might_sleep(); | 
|  | 156 |  | 
|  | 157 | if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON | | 
|  | 158 | BSS_CHANGED_BEACON_ENABLED) && | 
|  | 159 | sdata->vif.type != NL80211_IFTYPE_AP && | 
|  | 160 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | 
|  | 161 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 
|  | 162 | sdata->vif.type != NL80211_IFTYPE_OCB)) | 
|  | 163 | return; | 
|  | 164 |  | 
|  | 165 | if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || | 
|  | 166 | sdata->vif.type == NL80211_IFTYPE_NAN || | 
|  | 167 | (sdata->vif.type == NL80211_IFTYPE_MONITOR && | 
|  | 168 | !sdata->vif.mu_mimo_owner && | 
|  | 169 | !(changed & BSS_CHANGED_TXPOWER)))) | 
|  | 170 | return; | 
|  | 171 |  | 
|  | 172 | if (!check_sdata_in_driver(sdata)) | 
|  | 173 | return; | 
|  | 174 |  | 
|  | 175 | trace_drv_bss_info_changed(local, sdata, info, changed); | 
|  | 176 | if (local->ops->bss_info_changed) | 
|  | 177 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); | 
|  | 178 | trace_drv_return_void(local); | 
|  | 179 | } | 
|  | 180 |  | 
|  | 181 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 
|  | 182 | struct netdev_hw_addr_list *mc_list) | 
|  | 183 | { | 
|  | 184 | u64 ret = 0; | 
|  | 185 |  | 
|  | 186 | trace_drv_prepare_multicast(local, mc_list->count); | 
|  | 187 |  | 
|  | 188 | if (local->ops->prepare_multicast) | 
|  | 189 | ret = local->ops->prepare_multicast(&local->hw, mc_list); | 
|  | 190 |  | 
|  | 191 | trace_drv_return_u64(local, ret); | 
|  | 192 |  | 
|  | 193 | return ret; | 
|  | 194 | } | 
|  | 195 |  | 
|  | 196 | static inline void drv_configure_filter(struct ieee80211_local *local, | 
|  | 197 | unsigned int changed_flags, | 
|  | 198 | unsigned int *total_flags, | 
|  | 199 | u64 multicast) | 
|  | 200 | { | 
|  | 201 | might_sleep(); | 
|  | 202 |  | 
|  | 203 | trace_drv_configure_filter(local, changed_flags, total_flags, | 
|  | 204 | multicast); | 
|  | 205 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | 
|  | 206 | multicast); | 
|  | 207 | trace_drv_return_void(local); | 
|  | 208 | } | 
|  | 209 |  | 
|  | 210 | static inline void drv_config_iface_filter(struct ieee80211_local *local, | 
|  | 211 | struct ieee80211_sub_if_data *sdata, | 
|  | 212 | unsigned int filter_flags, | 
|  | 213 | unsigned int changed_flags) | 
|  | 214 | { | 
|  | 215 | might_sleep(); | 
|  | 216 |  | 
|  | 217 | trace_drv_config_iface_filter(local, sdata, filter_flags, | 
|  | 218 | changed_flags); | 
|  | 219 | if (local->ops->config_iface_filter) | 
|  | 220 | local->ops->config_iface_filter(&local->hw, &sdata->vif, | 
|  | 221 | filter_flags, | 
|  | 222 | changed_flags); | 
|  | 223 | trace_drv_return_void(local); | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | static inline int drv_set_tim(struct ieee80211_local *local, | 
|  | 227 | struct ieee80211_sta *sta, bool set) | 
|  | 228 | { | 
|  | 229 | int ret = 0; | 
|  | 230 | trace_drv_set_tim(local, sta, set); | 
|  | 231 | if (local->ops->set_tim) | 
|  | 232 | ret = local->ops->set_tim(&local->hw, sta, set); | 
|  | 233 | trace_drv_return_int(local, ret); | 
|  | 234 | return ret; | 
|  | 235 | } | 
|  | 236 |  | 
|  | 237 | static inline int drv_set_key(struct ieee80211_local *local, | 
|  | 238 | enum set_key_cmd cmd, | 
|  | 239 | struct ieee80211_sub_if_data *sdata, | 
|  | 240 | struct ieee80211_sta *sta, | 
|  | 241 | struct ieee80211_key_conf *key) | 
|  | 242 | { | 
|  | 243 | int ret; | 
|  | 244 |  | 
|  | 245 | might_sleep(); | 
|  | 246 |  | 
|  | 247 | sdata = get_bss_sdata(sdata); | 
|  | 248 | if (!check_sdata_in_driver(sdata)) | 
|  | 249 | return -EIO; | 
|  | 250 |  | 
|  | 251 | trace_drv_set_key(local, cmd, sdata, sta, key); | 
|  | 252 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | 
|  | 253 | trace_drv_return_int(local, ret); | 
|  | 254 | return ret; | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | static inline void drv_update_tkip_key(struct ieee80211_local *local, | 
|  | 258 | struct ieee80211_sub_if_data *sdata, | 
|  | 259 | struct ieee80211_key_conf *conf, | 
|  | 260 | struct sta_info *sta, u32 iv32, | 
|  | 261 | u16 *phase1key) | 
|  | 262 | { | 
|  | 263 | struct ieee80211_sta *ista = NULL; | 
|  | 264 |  | 
|  | 265 | if (sta) | 
|  | 266 | ista = &sta->sta; | 
|  | 267 |  | 
|  | 268 | sdata = get_bss_sdata(sdata); | 
|  | 269 | if (!check_sdata_in_driver(sdata)) | 
|  | 270 | return; | 
|  | 271 |  | 
|  | 272 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); | 
|  | 273 | if (local->ops->update_tkip_key) | 
|  | 274 | local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, | 
|  | 275 | ista, iv32, phase1key); | 
|  | 276 | trace_drv_return_void(local); | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | static inline int drv_hw_scan(struct ieee80211_local *local, | 
|  | 280 | struct ieee80211_sub_if_data *sdata, | 
|  | 281 | struct ieee80211_scan_request *req) | 
|  | 282 | { | 
|  | 283 | int ret; | 
|  | 284 |  | 
|  | 285 | might_sleep(); | 
|  | 286 |  | 
|  | 287 | if (!check_sdata_in_driver(sdata)) | 
|  | 288 | return -EIO; | 
|  | 289 |  | 
|  | 290 | trace_drv_hw_scan(local, sdata); | 
|  | 291 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); | 
|  | 292 | trace_drv_return_int(local, ret); | 
|  | 293 | return ret; | 
|  | 294 | } | 
|  | 295 |  | 
|  | 296 | static inline void drv_cancel_hw_scan(struct ieee80211_local *local, | 
|  | 297 | struct ieee80211_sub_if_data *sdata) | 
|  | 298 | { | 
|  | 299 | might_sleep(); | 
|  | 300 |  | 
|  | 301 | if (!check_sdata_in_driver(sdata)) | 
|  | 302 | return; | 
|  | 303 |  | 
|  | 304 | trace_drv_cancel_hw_scan(local, sdata); | 
|  | 305 | local->ops->cancel_hw_scan(&local->hw, &sdata->vif); | 
|  | 306 | trace_drv_return_void(local); | 
|  | 307 | } | 
|  | 308 |  | 
|  | 309 | static inline int | 
|  | 310 | drv_sched_scan_start(struct ieee80211_local *local, | 
|  | 311 | struct ieee80211_sub_if_data *sdata, | 
|  | 312 | struct cfg80211_sched_scan_request *req, | 
|  | 313 | struct ieee80211_scan_ies *ies) | 
|  | 314 | { | 
|  | 315 | int ret; | 
|  | 316 |  | 
|  | 317 | might_sleep(); | 
|  | 318 |  | 
|  | 319 | if (!check_sdata_in_driver(sdata)) | 
|  | 320 | return -EIO; | 
|  | 321 |  | 
|  | 322 | trace_drv_sched_scan_start(local, sdata); | 
|  | 323 | ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, | 
|  | 324 | req, ies); | 
|  | 325 | trace_drv_return_int(local, ret); | 
|  | 326 | return ret; | 
|  | 327 | } | 
|  | 328 |  | 
|  | 329 | static inline int drv_sched_scan_stop(struct ieee80211_local *local, | 
|  | 330 | struct ieee80211_sub_if_data *sdata) | 
|  | 331 | { | 
|  | 332 | int ret; | 
|  | 333 |  | 
|  | 334 | might_sleep(); | 
|  | 335 |  | 
|  | 336 | if (!check_sdata_in_driver(sdata)) | 
|  | 337 | return -EIO; | 
|  | 338 |  | 
|  | 339 | trace_drv_sched_scan_stop(local, sdata); | 
|  | 340 | ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); | 
|  | 341 | trace_drv_return_int(local, ret); | 
|  | 342 |  | 
|  | 343 | return ret; | 
|  | 344 | } | 
|  | 345 |  | 
|  | 346 | static inline void drv_sw_scan_start(struct ieee80211_local *local, | 
|  | 347 | struct ieee80211_sub_if_data *sdata, | 
|  | 348 | const u8 *mac_addr) | 
|  | 349 | { | 
|  | 350 | might_sleep(); | 
|  | 351 |  | 
|  | 352 | trace_drv_sw_scan_start(local, sdata, mac_addr); | 
|  | 353 | if (local->ops->sw_scan_start) | 
|  | 354 | local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr); | 
|  | 355 | trace_drv_return_void(local); | 
|  | 356 | } | 
|  | 357 |  | 
|  | 358 | static inline void drv_sw_scan_complete(struct ieee80211_local *local, | 
|  | 359 | struct ieee80211_sub_if_data *sdata) | 
|  | 360 | { | 
|  | 361 | might_sleep(); | 
|  | 362 |  | 
|  | 363 | trace_drv_sw_scan_complete(local, sdata); | 
|  | 364 | if (local->ops->sw_scan_complete) | 
|  | 365 | local->ops->sw_scan_complete(&local->hw, &sdata->vif); | 
|  | 366 | trace_drv_return_void(local); | 
|  | 367 | } | 
|  | 368 |  | 
|  | 369 | static inline int drv_get_stats(struct ieee80211_local *local, | 
|  | 370 | struct ieee80211_low_level_stats *stats) | 
|  | 371 | { | 
|  | 372 | int ret = -EOPNOTSUPP; | 
|  | 373 |  | 
|  | 374 | might_sleep(); | 
|  | 375 |  | 
|  | 376 | if (local->ops->get_stats) | 
|  | 377 | ret = local->ops->get_stats(&local->hw, stats); | 
|  | 378 | trace_drv_get_stats(local, stats, ret); | 
|  | 379 |  | 
|  | 380 | return ret; | 
|  | 381 | } | 
|  | 382 |  | 
|  | 383 | static inline void drv_get_key_seq(struct ieee80211_local *local, | 
|  | 384 | struct ieee80211_key *key, | 
|  | 385 | struct ieee80211_key_seq *seq) | 
|  | 386 | { | 
|  | 387 | if (local->ops->get_key_seq) | 
|  | 388 | local->ops->get_key_seq(&local->hw, &key->conf, seq); | 
|  | 389 | trace_drv_get_key_seq(local, &key->conf); | 
|  | 390 | } | 
|  | 391 |  | 
|  | 392 | static inline int drv_set_frag_threshold(struct ieee80211_local *local, | 
|  | 393 | u32 value) | 
|  | 394 | { | 
|  | 395 | int ret = 0; | 
|  | 396 |  | 
|  | 397 | might_sleep(); | 
|  | 398 |  | 
|  | 399 | trace_drv_set_frag_threshold(local, value); | 
|  | 400 | if (local->ops->set_frag_threshold) | 
|  | 401 | ret = local->ops->set_frag_threshold(&local->hw, value); | 
|  | 402 | trace_drv_return_int(local, ret); | 
|  | 403 | return ret; | 
|  | 404 | } | 
|  | 405 |  | 
|  | 406 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, | 
|  | 407 | u32 value) | 
|  | 408 | { | 
|  | 409 | int ret = 0; | 
|  | 410 |  | 
|  | 411 | might_sleep(); | 
|  | 412 |  | 
|  | 413 | trace_drv_set_rts_threshold(local, value); | 
|  | 414 | if (local->ops->set_rts_threshold) | 
|  | 415 | ret = local->ops->set_rts_threshold(&local->hw, value); | 
|  | 416 | trace_drv_return_int(local, ret); | 
|  | 417 | return ret; | 
|  | 418 | } | 
|  | 419 |  | 
|  | 420 | static inline int drv_set_coverage_class(struct ieee80211_local *local, | 
|  | 421 | s16 value) | 
|  | 422 | { | 
|  | 423 | int ret = 0; | 
|  | 424 | might_sleep(); | 
|  | 425 |  | 
|  | 426 | trace_drv_set_coverage_class(local, value); | 
|  | 427 | if (local->ops->set_coverage_class) | 
|  | 428 | local->ops->set_coverage_class(&local->hw, value); | 
|  | 429 | else | 
|  | 430 | ret = -EOPNOTSUPP; | 
|  | 431 |  | 
|  | 432 | trace_drv_return_int(local, ret); | 
|  | 433 | return ret; | 
|  | 434 | } | 
|  | 435 |  | 
|  | 436 | static inline void drv_sta_notify(struct ieee80211_local *local, | 
|  | 437 | struct ieee80211_sub_if_data *sdata, | 
|  | 438 | enum sta_notify_cmd cmd, | 
|  | 439 | struct ieee80211_sta *sta) | 
|  | 440 | { | 
|  | 441 | sdata = get_bss_sdata(sdata); | 
|  | 442 | if (!check_sdata_in_driver(sdata)) | 
|  | 443 | return; | 
|  | 444 |  | 
|  | 445 | trace_drv_sta_notify(local, sdata, cmd, sta); | 
|  | 446 | if (local->ops->sta_notify) | 
|  | 447 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); | 
|  | 448 | trace_drv_return_void(local); | 
|  | 449 | } | 
|  | 450 |  | 
|  | 451 | static inline int drv_sta_add(struct ieee80211_local *local, | 
|  | 452 | struct ieee80211_sub_if_data *sdata, | 
|  | 453 | struct ieee80211_sta *sta) | 
|  | 454 | { | 
|  | 455 | int ret = 0; | 
|  | 456 |  | 
|  | 457 | might_sleep(); | 
|  | 458 |  | 
|  | 459 | sdata = get_bss_sdata(sdata); | 
|  | 460 | if (!check_sdata_in_driver(sdata)) | 
|  | 461 | return -EIO; | 
|  | 462 |  | 
|  | 463 | trace_drv_sta_add(local, sdata, sta); | 
|  | 464 | if (local->ops->sta_add) | 
|  | 465 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); | 
|  | 466 |  | 
|  | 467 | trace_drv_return_int(local, ret); | 
|  | 468 |  | 
|  | 469 | return ret; | 
|  | 470 | } | 
|  | 471 |  | 
|  | 472 | static inline void drv_sta_remove(struct ieee80211_local *local, | 
|  | 473 | struct ieee80211_sub_if_data *sdata, | 
|  | 474 | struct ieee80211_sta *sta) | 
|  | 475 | { | 
|  | 476 | might_sleep(); | 
|  | 477 |  | 
|  | 478 | sdata = get_bss_sdata(sdata); | 
|  | 479 | if (!check_sdata_in_driver(sdata)) | 
|  | 480 | return; | 
|  | 481 |  | 
|  | 482 | trace_drv_sta_remove(local, sdata, sta); | 
|  | 483 | if (local->ops->sta_remove) | 
|  | 484 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); | 
|  | 485 |  | 
|  | 486 | trace_drv_return_void(local); | 
|  | 487 | } | 
|  | 488 |  | 
|  | 489 | #ifdef CONFIG_MAC80211_DEBUGFS | 
|  | 490 | static inline void drv_sta_add_debugfs(struct ieee80211_local *local, | 
|  | 491 | struct ieee80211_sub_if_data *sdata, | 
|  | 492 | struct ieee80211_sta *sta, | 
|  | 493 | struct dentry *dir) | 
|  | 494 | { | 
|  | 495 | might_sleep(); | 
|  | 496 |  | 
|  | 497 | sdata = get_bss_sdata(sdata); | 
|  | 498 | if (!check_sdata_in_driver(sdata)) | 
|  | 499 | return; | 
|  | 500 |  | 
|  | 501 | if (local->ops->sta_add_debugfs) | 
|  | 502 | local->ops->sta_add_debugfs(&local->hw, &sdata->vif, | 
|  | 503 | sta, dir); | 
|  | 504 | } | 
|  | 505 | #endif | 
|  | 506 |  | 
|  | 507 | static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, | 
|  | 508 | struct ieee80211_sub_if_data *sdata, | 
|  | 509 | struct sta_info *sta) | 
|  | 510 | { | 
|  | 511 | might_sleep(); | 
|  | 512 |  | 
|  | 513 | sdata = get_bss_sdata(sdata); | 
|  | 514 | if (!check_sdata_in_driver(sdata)) | 
|  | 515 | return; | 
|  | 516 |  | 
|  | 517 | trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); | 
|  | 518 | if (local->ops->sta_pre_rcu_remove) | 
|  | 519 | local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif, | 
|  | 520 | &sta->sta); | 
|  | 521 | trace_drv_return_void(local); | 
|  | 522 | } | 
|  | 523 |  | 
|  | 524 | __must_check | 
|  | 525 | int drv_sta_state(struct ieee80211_local *local, | 
|  | 526 | struct ieee80211_sub_if_data *sdata, | 
|  | 527 | struct sta_info *sta, | 
|  | 528 | enum ieee80211_sta_state old_state, | 
|  | 529 | enum ieee80211_sta_state new_state); | 
|  | 530 |  | 
|  | 531 | void drv_sta_rc_update(struct ieee80211_local *local, | 
|  | 532 | struct ieee80211_sub_if_data *sdata, | 
|  | 533 | struct ieee80211_sta *sta, u32 changed); | 
|  | 534 |  | 
|  | 535 | static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, | 
|  | 536 | struct ieee80211_sub_if_data *sdata, | 
|  | 537 | struct ieee80211_sta *sta) | 
|  | 538 | { | 
|  | 539 | sdata = get_bss_sdata(sdata); | 
|  | 540 | if (!check_sdata_in_driver(sdata)) | 
|  | 541 | return; | 
|  | 542 |  | 
|  | 543 | trace_drv_sta_rate_tbl_update(local, sdata, sta); | 
|  | 544 | if (local->ops->sta_rate_tbl_update) | 
|  | 545 | local->ops->sta_rate_tbl_update(&local->hw, &sdata->vif, sta); | 
|  | 546 |  | 
|  | 547 | trace_drv_return_void(local); | 
|  | 548 | } | 
|  | 549 |  | 
|  | 550 | static inline void drv_sta_statistics(struct ieee80211_local *local, | 
|  | 551 | struct ieee80211_sub_if_data *sdata, | 
|  | 552 | struct ieee80211_sta *sta, | 
|  | 553 | struct station_info *sinfo) | 
|  | 554 | { | 
|  | 555 | sdata = get_bss_sdata(sdata); | 
|  | 556 | if (!check_sdata_in_driver(sdata)) | 
|  | 557 | return; | 
|  | 558 |  | 
|  | 559 | trace_drv_sta_statistics(local, sdata, sta); | 
|  | 560 | if (local->ops->sta_statistics) | 
|  | 561 | local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo); | 
|  | 562 | trace_drv_return_void(local); | 
|  | 563 | } | 
|  | 564 |  | 
|  | 565 | int drv_conf_tx(struct ieee80211_local *local, | 
|  | 566 | struct ieee80211_sub_if_data *sdata, u16 ac, | 
|  | 567 | const struct ieee80211_tx_queue_params *params); | 
|  | 568 |  | 
|  | 569 | u64 drv_get_tsf(struct ieee80211_local *local, | 
|  | 570 | struct ieee80211_sub_if_data *sdata); | 
|  | 571 | void drv_set_tsf(struct ieee80211_local *local, | 
|  | 572 | struct ieee80211_sub_if_data *sdata, | 
|  | 573 | u64 tsf); | 
|  | 574 | void drv_offset_tsf(struct ieee80211_local *local, | 
|  | 575 | struct ieee80211_sub_if_data *sdata, | 
|  | 576 | s64 offset); | 
|  | 577 | void drv_reset_tsf(struct ieee80211_local *local, | 
|  | 578 | struct ieee80211_sub_if_data *sdata); | 
|  | 579 |  | 
|  | 580 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 
|  | 581 | { | 
|  | 582 | int ret = 0; /* default unsupported op for less congestion */ | 
|  | 583 |  | 
|  | 584 | might_sleep(); | 
|  | 585 |  | 
|  | 586 | trace_drv_tx_last_beacon(local); | 
|  | 587 | if (local->ops->tx_last_beacon) | 
|  | 588 | ret = local->ops->tx_last_beacon(&local->hw); | 
|  | 589 | trace_drv_return_int(local, ret); | 
|  | 590 | return ret; | 
|  | 591 | } | 
|  | 592 |  | 
|  | 593 | int drv_ampdu_action(struct ieee80211_local *local, | 
|  | 594 | struct ieee80211_sub_if_data *sdata, | 
|  | 595 | struct ieee80211_ampdu_params *params); | 
|  | 596 |  | 
|  | 597 | static inline int drv_get_survey(struct ieee80211_local *local, int idx, | 
|  | 598 | struct survey_info *survey) | 
|  | 599 | { | 
|  | 600 | int ret = -EOPNOTSUPP; | 
|  | 601 |  | 
|  | 602 | trace_drv_get_survey(local, idx, survey); | 
|  | 603 |  | 
|  | 604 | if (local->ops->get_survey) | 
|  | 605 | ret = local->ops->get_survey(&local->hw, idx, survey); | 
|  | 606 |  | 
|  | 607 | trace_drv_return_int(local, ret); | 
|  | 608 |  | 
|  | 609 | return ret; | 
|  | 610 | } | 
|  | 611 |  | 
|  | 612 | static inline void drv_rfkill_poll(struct ieee80211_local *local) | 
|  | 613 | { | 
|  | 614 | might_sleep(); | 
|  | 615 |  | 
|  | 616 | if (local->ops->rfkill_poll) | 
|  | 617 | local->ops->rfkill_poll(&local->hw); | 
|  | 618 | } | 
|  | 619 |  | 
|  | 620 | static inline void drv_flush(struct ieee80211_local *local, | 
|  | 621 | struct ieee80211_sub_if_data *sdata, | 
|  | 622 | u32 queues, bool drop) | 
|  | 623 | { | 
|  | 624 | struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; | 
|  | 625 |  | 
|  | 626 | might_sleep(); | 
|  | 627 |  | 
|  | 628 | if (sdata && !check_sdata_in_driver(sdata)) | 
|  | 629 | return; | 
|  | 630 |  | 
|  | 631 | trace_drv_flush(local, queues, drop); | 
|  | 632 | if (local->ops->flush) | 
|  | 633 | local->ops->flush(&local->hw, vif, queues, drop); | 
|  | 634 | trace_drv_return_void(local); | 
|  | 635 | } | 
|  | 636 |  | 
|  | 637 | static inline void drv_channel_switch(struct ieee80211_local *local, | 
|  | 638 | struct ieee80211_sub_if_data *sdata, | 
|  | 639 | struct ieee80211_channel_switch *ch_switch) | 
|  | 640 | { | 
|  | 641 | might_sleep(); | 
|  | 642 |  | 
|  | 643 | trace_drv_channel_switch(local, sdata, ch_switch); | 
|  | 644 | local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch); | 
|  | 645 | trace_drv_return_void(local); | 
|  | 646 | } | 
|  | 647 |  | 
|  | 648 |  | 
|  | 649 | static inline int drv_set_antenna(struct ieee80211_local *local, | 
|  | 650 | u32 tx_ant, u32 rx_ant) | 
|  | 651 | { | 
|  | 652 | int ret = -EOPNOTSUPP; | 
|  | 653 | might_sleep(); | 
|  | 654 | if (local->ops->set_antenna) | 
|  | 655 | ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant); | 
|  | 656 | trace_drv_set_antenna(local, tx_ant, rx_ant, ret); | 
|  | 657 | return ret; | 
|  | 658 | } | 
|  | 659 |  | 
|  | 660 | static inline int drv_get_antenna(struct ieee80211_local *local, | 
|  | 661 | u32 *tx_ant, u32 *rx_ant) | 
|  | 662 | { | 
|  | 663 | int ret = -EOPNOTSUPP; | 
|  | 664 | might_sleep(); | 
|  | 665 | if (local->ops->get_antenna) | 
|  | 666 | ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant); | 
|  | 667 | trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret); | 
|  | 668 | return ret; | 
|  | 669 | } | 
|  | 670 |  | 
|  | 671 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | 
|  | 672 | struct ieee80211_sub_if_data *sdata, | 
|  | 673 | struct ieee80211_channel *chan, | 
|  | 674 | unsigned int duration, | 
|  | 675 | enum ieee80211_roc_type type) | 
|  | 676 | { | 
|  | 677 | int ret; | 
|  | 678 |  | 
|  | 679 | might_sleep(); | 
|  | 680 |  | 
|  | 681 | trace_drv_remain_on_channel(local, sdata, chan, duration, type); | 
|  | 682 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, | 
|  | 683 | chan, duration, type); | 
|  | 684 | trace_drv_return_int(local, ret); | 
|  | 685 |  | 
|  | 686 | return ret; | 
|  | 687 | } | 
|  | 688 |  | 
|  | 689 | static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local) | 
|  | 690 | { | 
|  | 691 | int ret; | 
|  | 692 |  | 
|  | 693 | might_sleep(); | 
|  | 694 |  | 
|  | 695 | trace_drv_cancel_remain_on_channel(local); | 
|  | 696 | ret = local->ops->cancel_remain_on_channel(&local->hw); | 
|  | 697 | trace_drv_return_int(local, ret); | 
|  | 698 |  | 
|  | 699 | return ret; | 
|  | 700 | } | 
|  | 701 |  | 
|  | 702 | static inline int drv_set_ringparam(struct ieee80211_local *local, | 
|  | 703 | u32 tx, u32 rx) | 
|  | 704 | { | 
|  | 705 | int ret = -ENOTSUPP; | 
|  | 706 |  | 
|  | 707 | might_sleep(); | 
|  | 708 |  | 
|  | 709 | trace_drv_set_ringparam(local, tx, rx); | 
|  | 710 | if (local->ops->set_ringparam) | 
|  | 711 | ret = local->ops->set_ringparam(&local->hw, tx, rx); | 
|  | 712 | trace_drv_return_int(local, ret); | 
|  | 713 |  | 
|  | 714 | return ret; | 
|  | 715 | } | 
|  | 716 |  | 
|  | 717 | static inline void drv_get_ringparam(struct ieee80211_local *local, | 
|  | 718 | u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) | 
|  | 719 | { | 
|  | 720 | might_sleep(); | 
|  | 721 |  | 
|  | 722 | trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max); | 
|  | 723 | if (local->ops->get_ringparam) | 
|  | 724 | local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max); | 
|  | 725 | trace_drv_return_void(local); | 
|  | 726 | } | 
|  | 727 |  | 
|  | 728 | static inline bool drv_tx_frames_pending(struct ieee80211_local *local) | 
|  | 729 | { | 
|  | 730 | bool ret = false; | 
|  | 731 |  | 
|  | 732 | might_sleep(); | 
|  | 733 |  | 
|  | 734 | trace_drv_tx_frames_pending(local); | 
|  | 735 | if (local->ops->tx_frames_pending) | 
|  | 736 | ret = local->ops->tx_frames_pending(&local->hw); | 
|  | 737 | trace_drv_return_bool(local, ret); | 
|  | 738 |  | 
|  | 739 | return ret; | 
|  | 740 | } | 
|  | 741 |  | 
|  | 742 | static inline int drv_set_bitrate_mask(struct ieee80211_local *local, | 
|  | 743 | struct ieee80211_sub_if_data *sdata, | 
|  | 744 | const struct cfg80211_bitrate_mask *mask) | 
|  | 745 | { | 
|  | 746 | int ret = -EOPNOTSUPP; | 
|  | 747 |  | 
|  | 748 | might_sleep(); | 
|  | 749 |  | 
|  | 750 | if (!check_sdata_in_driver(sdata)) | 
|  | 751 | return -EIO; | 
|  | 752 |  | 
|  | 753 | trace_drv_set_bitrate_mask(local, sdata, mask); | 
|  | 754 | if (local->ops->set_bitrate_mask) | 
|  | 755 | ret = local->ops->set_bitrate_mask(&local->hw, | 
|  | 756 | &sdata->vif, mask); | 
|  | 757 | trace_drv_return_int(local, ret); | 
|  | 758 |  | 
|  | 759 | return ret; | 
|  | 760 | } | 
|  | 761 |  | 
|  | 762 | static inline void drv_set_rekey_data(struct ieee80211_local *local, | 
|  | 763 | struct ieee80211_sub_if_data *sdata, | 
|  | 764 | struct cfg80211_gtk_rekey_data *data) | 
|  | 765 | { | 
|  | 766 | if (!check_sdata_in_driver(sdata)) | 
|  | 767 | return; | 
|  | 768 |  | 
|  | 769 | trace_drv_set_rekey_data(local, sdata, data); | 
|  | 770 | if (local->ops->set_rekey_data) | 
|  | 771 | local->ops->set_rekey_data(&local->hw, &sdata->vif, data); | 
|  | 772 | trace_drv_return_void(local); | 
|  | 773 | } | 
|  | 774 |  | 
|  | 775 | static inline void drv_event_callback(struct ieee80211_local *local, | 
|  | 776 | struct ieee80211_sub_if_data *sdata, | 
|  | 777 | const struct ieee80211_event *event) | 
|  | 778 | { | 
|  | 779 | trace_drv_event_callback(local, sdata, event); | 
|  | 780 | if (local->ops->event_callback) | 
|  | 781 | local->ops->event_callback(&local->hw, &sdata->vif, event); | 
|  | 782 | trace_drv_return_void(local); | 
|  | 783 | } | 
|  | 784 |  | 
|  | 785 | static inline void | 
|  | 786 | drv_release_buffered_frames(struct ieee80211_local *local, | 
|  | 787 | struct sta_info *sta, u16 tids, int num_frames, | 
|  | 788 | enum ieee80211_frame_release_type reason, | 
|  | 789 | bool more_data) | 
|  | 790 | { | 
|  | 791 | trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames, | 
|  | 792 | reason, more_data); | 
|  | 793 | if (local->ops->release_buffered_frames) | 
|  | 794 | local->ops->release_buffered_frames(&local->hw, &sta->sta, tids, | 
|  | 795 | num_frames, reason, | 
|  | 796 | more_data); | 
|  | 797 | trace_drv_return_void(local); | 
|  | 798 | } | 
|  | 799 |  | 
|  | 800 | static inline void | 
|  | 801 | drv_allow_buffered_frames(struct ieee80211_local *local, | 
|  | 802 | struct sta_info *sta, u16 tids, int num_frames, | 
|  | 803 | enum ieee80211_frame_release_type reason, | 
|  | 804 | bool more_data) | 
|  | 805 | { | 
|  | 806 | trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames, | 
|  | 807 | reason, more_data); | 
|  | 808 | if (local->ops->allow_buffered_frames) | 
|  | 809 | local->ops->allow_buffered_frames(&local->hw, &sta->sta, | 
|  | 810 | tids, num_frames, reason, | 
|  | 811 | more_data); | 
|  | 812 | trace_drv_return_void(local); | 
|  | 813 | } | 
|  | 814 |  | 
|  | 815 | static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, | 
|  | 816 | struct ieee80211_sub_if_data *sdata) | 
|  | 817 | { | 
|  | 818 | might_sleep(); | 
|  | 819 |  | 
|  | 820 | if (!check_sdata_in_driver(sdata)) | 
|  | 821 | return; | 
|  | 822 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); | 
|  | 823 |  | 
|  | 824 | trace_drv_mgd_prepare_tx(local, sdata); | 
|  | 825 | if (local->ops->mgd_prepare_tx) | 
|  | 826 | local->ops->mgd_prepare_tx(&local->hw, &sdata->vif); | 
|  | 827 | trace_drv_return_void(local); | 
|  | 828 | } | 
|  | 829 |  | 
|  | 830 | static inline void | 
|  | 831 | drv_mgd_protect_tdls_discover(struct ieee80211_local *local, | 
|  | 832 | struct ieee80211_sub_if_data *sdata) | 
|  | 833 | { | 
|  | 834 | might_sleep(); | 
|  | 835 |  | 
|  | 836 | if (!check_sdata_in_driver(sdata)) | 
|  | 837 | return; | 
|  | 838 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); | 
|  | 839 |  | 
|  | 840 | trace_drv_mgd_protect_tdls_discover(local, sdata); | 
|  | 841 | if (local->ops->mgd_protect_tdls_discover) | 
|  | 842 | local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif); | 
|  | 843 | trace_drv_return_void(local); | 
|  | 844 | } | 
|  | 845 |  | 
|  | 846 | static inline int drv_add_chanctx(struct ieee80211_local *local, | 
|  | 847 | struct ieee80211_chanctx *ctx) | 
|  | 848 | { | 
|  | 849 | int ret = -EOPNOTSUPP; | 
|  | 850 |  | 
|  | 851 | might_sleep(); | 
|  | 852 |  | 
|  | 853 | trace_drv_add_chanctx(local, ctx); | 
|  | 854 | if (local->ops->add_chanctx) | 
|  | 855 | ret = local->ops->add_chanctx(&local->hw, &ctx->conf); | 
|  | 856 | trace_drv_return_int(local, ret); | 
|  | 857 | if (!ret) | 
|  | 858 | ctx->driver_present = true; | 
|  | 859 |  | 
|  | 860 | return ret; | 
|  | 861 | } | 
|  | 862 |  | 
|  | 863 | static inline void drv_remove_chanctx(struct ieee80211_local *local, | 
|  | 864 | struct ieee80211_chanctx *ctx) | 
|  | 865 | { | 
|  | 866 | might_sleep(); | 
|  | 867 |  | 
|  | 868 | if (WARN_ON(!ctx->driver_present)) | 
|  | 869 | return; | 
|  | 870 |  | 
|  | 871 | trace_drv_remove_chanctx(local, ctx); | 
|  | 872 | if (local->ops->remove_chanctx) | 
|  | 873 | local->ops->remove_chanctx(&local->hw, &ctx->conf); | 
|  | 874 | trace_drv_return_void(local); | 
|  | 875 | ctx->driver_present = false; | 
|  | 876 | } | 
|  | 877 |  | 
|  | 878 | static inline void drv_change_chanctx(struct ieee80211_local *local, | 
|  | 879 | struct ieee80211_chanctx *ctx, | 
|  | 880 | u32 changed) | 
|  | 881 | { | 
|  | 882 | might_sleep(); | 
|  | 883 |  | 
|  | 884 | trace_drv_change_chanctx(local, ctx, changed); | 
|  | 885 | if (local->ops->change_chanctx) { | 
|  | 886 | WARN_ON_ONCE(!ctx->driver_present); | 
|  | 887 | local->ops->change_chanctx(&local->hw, &ctx->conf, changed); | 
|  | 888 | } | 
|  | 889 | trace_drv_return_void(local); | 
|  | 890 | } | 
|  | 891 |  | 
|  | 892 | static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, | 
|  | 893 | struct ieee80211_sub_if_data *sdata, | 
|  | 894 | struct ieee80211_chanctx *ctx) | 
|  | 895 | { | 
|  | 896 | int ret = 0; | 
|  | 897 |  | 
|  | 898 | if (!check_sdata_in_driver(sdata)) | 
|  | 899 | return -EIO; | 
|  | 900 |  | 
|  | 901 | trace_drv_assign_vif_chanctx(local, sdata, ctx); | 
|  | 902 | if (local->ops->assign_vif_chanctx) { | 
|  | 903 | WARN_ON_ONCE(!ctx->driver_present); | 
|  | 904 | ret = local->ops->assign_vif_chanctx(&local->hw, | 
|  | 905 | &sdata->vif, | 
|  | 906 | &ctx->conf); | 
|  | 907 | } | 
|  | 908 | trace_drv_return_int(local, ret); | 
|  | 909 |  | 
|  | 910 | return ret; | 
|  | 911 | } | 
|  | 912 |  | 
|  | 913 | static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, | 
|  | 914 | struct ieee80211_sub_if_data *sdata, | 
|  | 915 | struct ieee80211_chanctx *ctx) | 
|  | 916 | { | 
|  | 917 | might_sleep(); | 
|  | 918 |  | 
|  | 919 | if (!check_sdata_in_driver(sdata)) | 
|  | 920 | return; | 
|  | 921 |  | 
|  | 922 | trace_drv_unassign_vif_chanctx(local, sdata, ctx); | 
|  | 923 | if (local->ops->unassign_vif_chanctx) { | 
|  | 924 | WARN_ON_ONCE(!ctx->driver_present); | 
|  | 925 | local->ops->unassign_vif_chanctx(&local->hw, | 
|  | 926 | &sdata->vif, | 
|  | 927 | &ctx->conf); | 
|  | 928 | } | 
|  | 929 | trace_drv_return_void(local); | 
|  | 930 | } | 
|  | 931 |  | 
|  | 932 | int drv_switch_vif_chanctx(struct ieee80211_local *local, | 
|  | 933 | struct ieee80211_vif_chanctx_switch *vifs, | 
|  | 934 | int n_vifs, enum ieee80211_chanctx_switch_mode mode); | 
|  | 935 |  | 
|  | 936 | static inline int drv_start_ap(struct ieee80211_local *local, | 
|  | 937 | struct ieee80211_sub_if_data *sdata) | 
|  | 938 | { | 
|  | 939 | int ret = 0; | 
|  | 940 |  | 
|  | 941 | might_sleep(); | 
|  | 942 |  | 
|  | 943 | if (!check_sdata_in_driver(sdata)) | 
|  | 944 | return -EIO; | 
|  | 945 |  | 
|  | 946 | trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); | 
|  | 947 | if (local->ops->start_ap) | 
|  | 948 | ret = local->ops->start_ap(&local->hw, &sdata->vif); | 
|  | 949 | trace_drv_return_int(local, ret); | 
|  | 950 | return ret; | 
|  | 951 | } | 
|  | 952 |  | 
|  | 953 | static inline void drv_stop_ap(struct ieee80211_local *local, | 
|  | 954 | struct ieee80211_sub_if_data *sdata) | 
|  | 955 | { | 
|  | 956 | if (!check_sdata_in_driver(sdata)) | 
|  | 957 | return; | 
|  | 958 |  | 
|  | 959 | trace_drv_stop_ap(local, sdata); | 
|  | 960 | if (local->ops->stop_ap) | 
|  | 961 | local->ops->stop_ap(&local->hw, &sdata->vif); | 
|  | 962 | trace_drv_return_void(local); | 
|  | 963 | } | 
|  | 964 |  | 
|  | 965 | static inline void | 
|  | 966 | drv_reconfig_complete(struct ieee80211_local *local, | 
|  | 967 | enum ieee80211_reconfig_type reconfig_type) | 
|  | 968 | { | 
|  | 969 | might_sleep(); | 
|  | 970 |  | 
|  | 971 | trace_drv_reconfig_complete(local, reconfig_type); | 
|  | 972 | if (local->ops->reconfig_complete) | 
|  | 973 | local->ops->reconfig_complete(&local->hw, reconfig_type); | 
|  | 974 | trace_drv_return_void(local); | 
|  | 975 | } | 
|  | 976 |  | 
|  | 977 | static inline void | 
|  | 978 | drv_set_default_unicast_key(struct ieee80211_local *local, | 
|  | 979 | struct ieee80211_sub_if_data *sdata, | 
|  | 980 | int key_idx) | 
|  | 981 | { | 
|  | 982 | if (!check_sdata_in_driver(sdata)) | 
|  | 983 | return; | 
|  | 984 |  | 
|  | 985 | WARN_ON_ONCE(key_idx < -1 || key_idx > 3); | 
|  | 986 |  | 
|  | 987 | trace_drv_set_default_unicast_key(local, sdata, key_idx); | 
|  | 988 | if (local->ops->set_default_unicast_key) | 
|  | 989 | local->ops->set_default_unicast_key(&local->hw, &sdata->vif, | 
|  | 990 | key_idx); | 
|  | 991 | trace_drv_return_void(local); | 
|  | 992 | } | 
|  | 993 |  | 
|  | 994 | #if IS_ENABLED(CONFIG_IPV6) | 
|  | 995 | static inline void drv_ipv6_addr_change(struct ieee80211_local *local, | 
|  | 996 | struct ieee80211_sub_if_data *sdata, | 
|  | 997 | struct inet6_dev *idev) | 
|  | 998 | { | 
|  | 999 | trace_drv_ipv6_addr_change(local, sdata); | 
|  | 1000 | if (local->ops->ipv6_addr_change) | 
|  | 1001 | local->ops->ipv6_addr_change(&local->hw, &sdata->vif, idev); | 
|  | 1002 | trace_drv_return_void(local); | 
|  | 1003 | } | 
|  | 1004 | #endif | 
|  | 1005 |  | 
|  | 1006 | static inline void | 
|  | 1007 | drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata, | 
|  | 1008 | struct cfg80211_chan_def *chandef) | 
|  | 1009 | { | 
|  | 1010 | struct ieee80211_local *local = sdata->local; | 
|  | 1011 |  | 
|  | 1012 | if (local->ops->channel_switch_beacon) { | 
|  | 1013 | trace_drv_channel_switch_beacon(local, sdata, chandef); | 
|  | 1014 | local->ops->channel_switch_beacon(&local->hw, &sdata->vif, | 
|  | 1015 | chandef); | 
|  | 1016 | } | 
|  | 1017 | } | 
|  | 1018 |  | 
|  | 1019 | static inline int | 
|  | 1020 | drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata, | 
|  | 1021 | struct ieee80211_channel_switch *ch_switch) | 
|  | 1022 | { | 
|  | 1023 | struct ieee80211_local *local = sdata->local; | 
|  | 1024 | int ret = 0; | 
|  | 1025 |  | 
|  | 1026 | if (!check_sdata_in_driver(sdata)) | 
|  | 1027 | return -EIO; | 
|  | 1028 |  | 
|  | 1029 | trace_drv_pre_channel_switch(local, sdata, ch_switch); | 
|  | 1030 | if (local->ops->pre_channel_switch) | 
|  | 1031 | ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif, | 
|  | 1032 | ch_switch); | 
|  | 1033 | trace_drv_return_int(local, ret); | 
|  | 1034 | return ret; | 
|  | 1035 | } | 
|  | 1036 |  | 
|  | 1037 | static inline int | 
|  | 1038 | drv_post_channel_switch(struct ieee80211_sub_if_data *sdata) | 
|  | 1039 | { | 
|  | 1040 | struct ieee80211_local *local = sdata->local; | 
|  | 1041 | int ret = 0; | 
|  | 1042 |  | 
|  | 1043 | if (!check_sdata_in_driver(sdata)) | 
|  | 1044 | return -EIO; | 
|  | 1045 |  | 
|  | 1046 | trace_drv_post_channel_switch(local, sdata); | 
|  | 1047 | if (local->ops->post_channel_switch) | 
|  | 1048 | ret = local->ops->post_channel_switch(&local->hw, &sdata->vif); | 
|  | 1049 | trace_drv_return_int(local, ret); | 
|  | 1050 | return ret; | 
|  | 1051 | } | 
|  | 1052 |  | 
|  | 1053 | static inline int drv_join_ibss(struct ieee80211_local *local, | 
|  | 1054 | struct ieee80211_sub_if_data *sdata) | 
|  | 1055 | { | 
|  | 1056 | int ret = 0; | 
|  | 1057 |  | 
|  | 1058 | might_sleep(); | 
|  | 1059 | if (!check_sdata_in_driver(sdata)) | 
|  | 1060 | return -EIO; | 
|  | 1061 |  | 
|  | 1062 | trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); | 
|  | 1063 | if (local->ops->join_ibss) | 
|  | 1064 | ret = local->ops->join_ibss(&local->hw, &sdata->vif); | 
|  | 1065 | trace_drv_return_int(local, ret); | 
|  | 1066 | return ret; | 
|  | 1067 | } | 
|  | 1068 |  | 
|  | 1069 | static inline void drv_leave_ibss(struct ieee80211_local *local, | 
|  | 1070 | struct ieee80211_sub_if_data *sdata) | 
|  | 1071 | { | 
|  | 1072 | might_sleep(); | 
|  | 1073 | if (!check_sdata_in_driver(sdata)) | 
|  | 1074 | return; | 
|  | 1075 |  | 
|  | 1076 | trace_drv_leave_ibss(local, sdata); | 
|  | 1077 | if (local->ops->leave_ibss) | 
|  | 1078 | local->ops->leave_ibss(&local->hw, &sdata->vif); | 
|  | 1079 | trace_drv_return_void(local); | 
|  | 1080 | } | 
|  | 1081 |  | 
|  | 1082 | static inline u32 drv_get_expected_throughput(struct ieee80211_local *local, | 
|  | 1083 | struct sta_info *sta) | 
|  | 1084 | { | 
|  | 1085 | u32 ret = 0; | 
|  | 1086 |  | 
|  | 1087 | trace_drv_get_expected_throughput(&sta->sta); | 
|  | 1088 | if (local->ops->get_expected_throughput && sta->uploaded) | 
|  | 1089 | ret = local->ops->get_expected_throughput(&local->hw, &sta->sta); | 
|  | 1090 | trace_drv_return_u32(local, ret); | 
|  | 1091 |  | 
|  | 1092 | return ret; | 
|  | 1093 | } | 
|  | 1094 |  | 
|  | 1095 | static inline int drv_get_txpower(struct ieee80211_local *local, | 
|  | 1096 | struct ieee80211_sub_if_data *sdata, int *dbm) | 
|  | 1097 | { | 
|  | 1098 | int ret; | 
|  | 1099 |  | 
|  | 1100 | if (!local->ops->get_txpower) | 
|  | 1101 | return -EOPNOTSUPP; | 
|  | 1102 |  | 
|  | 1103 | ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm); | 
|  | 1104 | trace_drv_get_txpower(local, sdata, *dbm, ret); | 
|  | 1105 |  | 
|  | 1106 | return ret; | 
|  | 1107 | } | 
|  | 1108 |  | 
|  | 1109 | static inline int | 
|  | 1110 | drv_tdls_channel_switch(struct ieee80211_local *local, | 
|  | 1111 | struct ieee80211_sub_if_data *sdata, | 
|  | 1112 | struct ieee80211_sta *sta, u8 oper_class, | 
|  | 1113 | struct cfg80211_chan_def *chandef, | 
|  | 1114 | struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie) | 
|  | 1115 | { | 
|  | 1116 | int ret; | 
|  | 1117 |  | 
|  | 1118 | might_sleep(); | 
|  | 1119 | if (!check_sdata_in_driver(sdata)) | 
|  | 1120 | return -EIO; | 
|  | 1121 |  | 
|  | 1122 | if (!local->ops->tdls_channel_switch) | 
|  | 1123 | return -EOPNOTSUPP; | 
|  | 1124 |  | 
|  | 1125 | trace_drv_tdls_channel_switch(local, sdata, sta, oper_class, chandef); | 
|  | 1126 | ret = local->ops->tdls_channel_switch(&local->hw, &sdata->vif, sta, | 
|  | 1127 | oper_class, chandef, tmpl_skb, | 
|  | 1128 | ch_sw_tm_ie); | 
|  | 1129 | trace_drv_return_int(local, ret); | 
|  | 1130 | return ret; | 
|  | 1131 | } | 
|  | 1132 |  | 
|  | 1133 | static inline void | 
|  | 1134 | drv_tdls_cancel_channel_switch(struct ieee80211_local *local, | 
|  | 1135 | struct ieee80211_sub_if_data *sdata, | 
|  | 1136 | struct ieee80211_sta *sta) | 
|  | 1137 | { | 
|  | 1138 | might_sleep(); | 
|  | 1139 | if (!check_sdata_in_driver(sdata)) | 
|  | 1140 | return; | 
|  | 1141 |  | 
|  | 1142 | if (!local->ops->tdls_cancel_channel_switch) | 
|  | 1143 | return; | 
|  | 1144 |  | 
|  | 1145 | trace_drv_tdls_cancel_channel_switch(local, sdata, sta); | 
|  | 1146 | local->ops->tdls_cancel_channel_switch(&local->hw, &sdata->vif, sta); | 
|  | 1147 | trace_drv_return_void(local); | 
|  | 1148 | } | 
|  | 1149 |  | 
|  | 1150 | static inline void | 
|  | 1151 | drv_tdls_recv_channel_switch(struct ieee80211_local *local, | 
|  | 1152 | struct ieee80211_sub_if_data *sdata, | 
|  | 1153 | struct ieee80211_tdls_ch_sw_params *params) | 
|  | 1154 | { | 
|  | 1155 | trace_drv_tdls_recv_channel_switch(local, sdata, params); | 
|  | 1156 | if (local->ops->tdls_recv_channel_switch) | 
|  | 1157 | local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif, | 
|  | 1158 | params); | 
|  | 1159 | trace_drv_return_void(local); | 
|  | 1160 | } | 
|  | 1161 |  | 
|  | 1162 | static inline void drv_wake_tx_queue(struct ieee80211_local *local, | 
|  | 1163 | struct txq_info *txq) | 
|  | 1164 | { | 
|  | 1165 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); | 
|  | 1166 |  | 
|  | 1167 | if (local->in_reconfig) | 
|  | 1168 | return; | 
|  | 1169 |  | 
|  | 1170 | if (!check_sdata_in_driver(sdata)) | 
|  | 1171 | return; | 
|  | 1172 |  | 
|  | 1173 | trace_drv_wake_tx_queue(local, sdata, txq); | 
|  | 1174 | local->ops->wake_tx_queue(&local->hw, &txq->txq); | 
|  | 1175 | } | 
|  | 1176 |  | 
|  | 1177 | static inline int drv_start_nan(struct ieee80211_local *local, | 
|  | 1178 | struct ieee80211_sub_if_data *sdata, | 
|  | 1179 | struct cfg80211_nan_conf *conf) | 
|  | 1180 | { | 
|  | 1181 | int ret; | 
|  | 1182 |  | 
|  | 1183 | might_sleep(); | 
|  | 1184 | check_sdata_in_driver(sdata); | 
|  | 1185 |  | 
|  | 1186 | trace_drv_start_nan(local, sdata, conf); | 
|  | 1187 | ret = local->ops->start_nan(&local->hw, &sdata->vif, conf); | 
|  | 1188 | trace_drv_return_int(local, ret); | 
|  | 1189 | return ret; | 
|  | 1190 | } | 
|  | 1191 |  | 
|  | 1192 | static inline void drv_stop_nan(struct ieee80211_local *local, | 
|  | 1193 | struct ieee80211_sub_if_data *sdata) | 
|  | 1194 | { | 
|  | 1195 | might_sleep(); | 
|  | 1196 | check_sdata_in_driver(sdata); | 
|  | 1197 |  | 
|  | 1198 | trace_drv_stop_nan(local, sdata); | 
|  | 1199 | local->ops->stop_nan(&local->hw, &sdata->vif); | 
|  | 1200 | trace_drv_return_void(local); | 
|  | 1201 | } | 
|  | 1202 |  | 
|  | 1203 | static inline int drv_nan_change_conf(struct ieee80211_local *local, | 
|  | 1204 | struct ieee80211_sub_if_data *sdata, | 
|  | 1205 | struct cfg80211_nan_conf *conf, | 
|  | 1206 | u32 changes) | 
|  | 1207 | { | 
|  | 1208 | int ret; | 
|  | 1209 |  | 
|  | 1210 | might_sleep(); | 
|  | 1211 | check_sdata_in_driver(sdata); | 
|  | 1212 |  | 
|  | 1213 | if (!local->ops->nan_change_conf) | 
|  | 1214 | return -EOPNOTSUPP; | 
|  | 1215 |  | 
|  | 1216 | trace_drv_nan_change_conf(local, sdata, conf, changes); | 
|  | 1217 | ret = local->ops->nan_change_conf(&local->hw, &sdata->vif, conf, | 
|  | 1218 | changes); | 
|  | 1219 | trace_drv_return_int(local, ret); | 
|  | 1220 |  | 
|  | 1221 | return ret; | 
|  | 1222 | } | 
|  | 1223 |  | 
|  | 1224 | static inline int drv_add_nan_func(struct ieee80211_local *local, | 
|  | 1225 | struct ieee80211_sub_if_data *sdata, | 
|  | 1226 | const struct cfg80211_nan_func *nan_func) | 
|  | 1227 | { | 
|  | 1228 | int ret; | 
|  | 1229 |  | 
|  | 1230 | might_sleep(); | 
|  | 1231 | check_sdata_in_driver(sdata); | 
|  | 1232 |  | 
|  | 1233 | if (!local->ops->add_nan_func) | 
|  | 1234 | return -EOPNOTSUPP; | 
|  | 1235 |  | 
|  | 1236 | trace_drv_add_nan_func(local, sdata, nan_func); | 
|  | 1237 | ret = local->ops->add_nan_func(&local->hw, &sdata->vif, nan_func); | 
|  | 1238 | trace_drv_return_int(local, ret); | 
|  | 1239 |  | 
|  | 1240 | return ret; | 
|  | 1241 | } | 
|  | 1242 |  | 
|  | 1243 | static inline void drv_del_nan_func(struct ieee80211_local *local, | 
|  | 1244 | struct ieee80211_sub_if_data *sdata, | 
|  | 1245 | u8 instance_id) | 
|  | 1246 | { | 
|  | 1247 | might_sleep(); | 
|  | 1248 | check_sdata_in_driver(sdata); | 
|  | 1249 |  | 
|  | 1250 | trace_drv_del_nan_func(local, sdata, instance_id); | 
|  | 1251 | if (local->ops->del_nan_func) | 
|  | 1252 | local->ops->del_nan_func(&local->hw, &sdata->vif, instance_id); | 
|  | 1253 | trace_drv_return_void(local); | 
|  | 1254 | } | 
|  | 1255 |  | 
|  | 1256 | #endif /* __MAC80211_DRIVER_OPS */ |