124487981SJohannes Berg #ifndef __MAC80211_DRIVER_OPS 224487981SJohannes Berg #define __MAC80211_DRIVER_OPS 324487981SJohannes Berg 424487981SJohannes Berg #include <net/mac80211.h> 524487981SJohannes Berg #include "ieee80211_i.h" 6011ad0e9SJohannes Berg #include "trace.h" 724487981SJohannes Berg 8f6837ba8SJohannes Berg static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) 97b7eab6fSJohannes Berg { 10f6837ba8SJohannes Berg return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), 11d17087e7SBen Greear "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", 12f142c6b9SJohannes Berg sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); 137b7eab6fSJohannes Berg } 147b7eab6fSJohannes Berg 15bc192f89SFelix Fietkau static inline struct ieee80211_sub_if_data * 16bc192f89SFelix Fietkau get_bss_sdata(struct ieee80211_sub_if_data *sdata) 17bc192f89SFelix Fietkau { 18bc192f89SFelix Fietkau if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 19bc192f89SFelix Fietkau sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, 20bc192f89SFelix Fietkau u.ap); 21bc192f89SFelix Fietkau 22bc192f89SFelix Fietkau return sdata; 23bc192f89SFelix Fietkau } 24bc192f89SFelix Fietkau 2536323f81SThomas Huehn static inline void drv_tx(struct ieee80211_local *local, 2636323f81SThomas Huehn struct ieee80211_tx_control *control, 2736323f81SThomas Huehn struct sk_buff *skb) 2824487981SJohannes Berg { 2936323f81SThomas Huehn local->ops->tx(&local->hw, control, skb); 3024487981SJohannes Berg } 3124487981SJohannes Berg 32e352114fSBen Greear static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, 33e352114fSBen Greear u32 sset, u8 *data) 34e352114fSBen Greear { 35e352114fSBen Greear struct ieee80211_local *local = sdata->local; 36e352114fSBen Greear if (local->ops->get_et_strings) { 37e352114fSBen Greear trace_drv_get_et_strings(local, sset); 38e352114fSBen Greear local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data); 39e352114fSBen Greear trace_drv_return_void(local); 40e352114fSBen Greear } 41e352114fSBen Greear } 42e352114fSBen Greear 43e352114fSBen Greear static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata, 44e352114fSBen Greear struct ethtool_stats *stats, 45e352114fSBen Greear u64 *data) 46e352114fSBen Greear { 47e352114fSBen Greear struct ieee80211_local *local = sdata->local; 48e352114fSBen Greear if (local->ops->get_et_stats) { 49e352114fSBen Greear trace_drv_get_et_stats(local); 50e352114fSBen Greear local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data); 51e352114fSBen Greear trace_drv_return_void(local); 52e352114fSBen Greear } 53e352114fSBen Greear } 54e352114fSBen Greear 55e352114fSBen Greear static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata, 56e352114fSBen Greear int sset) 57e352114fSBen Greear { 58e352114fSBen Greear struct ieee80211_local *local = sdata->local; 59e352114fSBen Greear int rv = 0; 60e352114fSBen Greear if (local->ops->get_et_sset_count) { 61e352114fSBen Greear trace_drv_get_et_sset_count(local, sset); 62e352114fSBen Greear rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif, 63e352114fSBen Greear sset); 64e352114fSBen Greear trace_drv_return_int(local, rv); 65e352114fSBen Greear } 66e352114fSBen Greear return rv; 67e352114fSBen Greear } 68e352114fSBen Greear 6924487981SJohannes Berg static inline int drv_start(struct ieee80211_local *local) 7024487981SJohannes Berg { 71ea77f12fSJohannes Berg int ret; 72ea77f12fSJohannes Berg 73e1781ed3SKalle Valo might_sleep(); 74e1781ed3SKalle Valo 754efc76bdSJohannes Berg trace_drv_start(local); 76ea77f12fSJohannes Berg local->started = true; 77ea77f12fSJohannes Berg smp_mb(); 78ea77f12fSJohannes Berg ret = local->ops->start(&local->hw); 794efc76bdSJohannes Berg trace_drv_return_int(local, ret); 800a2b8bb2SJohannes Berg return ret; 8124487981SJohannes Berg } 8224487981SJohannes Berg 8324487981SJohannes Berg static inline void drv_stop(struct ieee80211_local *local) 8424487981SJohannes Berg { 85e1781ed3SKalle Valo might_sleep(); 86e1781ed3SKalle Valo 870a2b8bb2SJohannes Berg trace_drv_stop(local); 884efc76bdSJohannes Berg local->ops->stop(&local->hw); 894efc76bdSJohannes Berg trace_drv_return_void(local); 90ea77f12fSJohannes Berg 91ea77f12fSJohannes Berg /* sync away all work on the tasklet before clearing started */ 92ea77f12fSJohannes Berg tasklet_disable(&local->tasklet); 93ea77f12fSJohannes Berg tasklet_enable(&local->tasklet); 94ea77f12fSJohannes Berg 95ea77f12fSJohannes Berg barrier(); 96ea77f12fSJohannes Berg 97ea77f12fSJohannes Berg local->started = false; 9824487981SJohannes Berg } 9924487981SJohannes Berg 100eecc4800SJohannes Berg #ifdef CONFIG_PM 101eecc4800SJohannes Berg static inline int drv_suspend(struct ieee80211_local *local, 102eecc4800SJohannes Berg struct cfg80211_wowlan *wowlan) 103eecc4800SJohannes Berg { 104eecc4800SJohannes Berg int ret; 105eecc4800SJohannes Berg 106eecc4800SJohannes Berg might_sleep(); 107eecc4800SJohannes Berg 108eecc4800SJohannes Berg trace_drv_suspend(local); 109eecc4800SJohannes Berg ret = local->ops->suspend(&local->hw, wowlan); 110eecc4800SJohannes Berg trace_drv_return_int(local, ret); 111eecc4800SJohannes Berg return ret; 112eecc4800SJohannes Berg } 113eecc4800SJohannes Berg 114eecc4800SJohannes Berg static inline int drv_resume(struct ieee80211_local *local) 115eecc4800SJohannes Berg { 116eecc4800SJohannes Berg int ret; 117eecc4800SJohannes Berg 118eecc4800SJohannes Berg might_sleep(); 119eecc4800SJohannes Berg 120eecc4800SJohannes Berg trace_drv_resume(local); 121eecc4800SJohannes Berg ret = local->ops->resume(&local->hw); 122eecc4800SJohannes Berg trace_drv_return_int(local, ret); 123eecc4800SJohannes Berg return ret; 124eecc4800SJohannes Berg } 1256d52563fSJohannes Berg 1266d52563fSJohannes Berg static inline void drv_set_wakeup(struct ieee80211_local *local, 1276d52563fSJohannes Berg bool enabled) 1286d52563fSJohannes Berg { 1296d52563fSJohannes Berg might_sleep(); 1306d52563fSJohannes Berg 1316d52563fSJohannes Berg if (!local->ops->set_wakeup) 1326d52563fSJohannes Berg return; 1336d52563fSJohannes Berg 1346d52563fSJohannes Berg trace_drv_set_wakeup(local, enabled); 1356d52563fSJohannes Berg local->ops->set_wakeup(&local->hw, enabled); 1366d52563fSJohannes Berg trace_drv_return_void(local); 1376d52563fSJohannes Berg } 138eecc4800SJohannes Berg #endif 139eecc4800SJohannes Berg 14024487981SJohannes Berg static inline int drv_add_interface(struct ieee80211_local *local, 1417b7eab6fSJohannes Berg struct ieee80211_sub_if_data *sdata) 14224487981SJohannes Berg { 143e1781ed3SKalle Valo int ret; 144e1781ed3SKalle Valo 145e1781ed3SKalle Valo might_sleep(); 146e1781ed3SKalle Valo 1477b7eab6fSJohannes Berg if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || 1484b6f1dd6SJohannes Berg (sdata->vif.type == NL80211_IFTYPE_MONITOR && 14930686bf7SJohannes Berg !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && 15031eba5bcSFelix Fietkau !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)))) 1517b7eab6fSJohannes Berg return -EINVAL; 1527b7eab6fSJohannes Berg 1537b7eab6fSJohannes Berg trace_drv_add_interface(local, sdata); 1547b7eab6fSJohannes Berg ret = local->ops->add_interface(&local->hw, &sdata->vif); 1554efc76bdSJohannes Berg trace_drv_return_int(local, ret); 1567b7eab6fSJohannes Berg 1577b7eab6fSJohannes Berg if (ret == 0) 1587b7eab6fSJohannes Berg sdata->flags |= IEEE80211_SDATA_IN_DRIVER; 1597b7eab6fSJohannes Berg 1600a2b8bb2SJohannes Berg return ret; 16124487981SJohannes Berg } 16224487981SJohannes Berg 16334d4bc4dSJohannes Berg static inline int drv_change_interface(struct ieee80211_local *local, 16434d4bc4dSJohannes Berg struct ieee80211_sub_if_data *sdata, 1652ca27bcfSJohannes Berg enum nl80211_iftype type, bool p2p) 16634d4bc4dSJohannes Berg { 16734d4bc4dSJohannes Berg int ret; 16834d4bc4dSJohannes Berg 16934d4bc4dSJohannes Berg might_sleep(); 17034d4bc4dSJohannes Berg 171f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 172f6837ba8SJohannes Berg return -EIO; 1737b7eab6fSJohannes Berg 1742ca27bcfSJohannes Berg trace_drv_change_interface(local, sdata, type, p2p); 1752ca27bcfSJohannes Berg ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); 17634d4bc4dSJohannes Berg trace_drv_return_int(local, ret); 17734d4bc4dSJohannes Berg return ret; 17834d4bc4dSJohannes Berg } 17934d4bc4dSJohannes Berg 18024487981SJohannes Berg static inline void drv_remove_interface(struct ieee80211_local *local, 1817b7eab6fSJohannes Berg struct ieee80211_sub_if_data *sdata) 18224487981SJohannes Berg { 183e1781ed3SKalle Valo might_sleep(); 184e1781ed3SKalle Valo 185f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 186f6837ba8SJohannes Berg return; 1877b7eab6fSJohannes Berg 1887b7eab6fSJohannes Berg trace_drv_remove_interface(local, sdata); 1897b7eab6fSJohannes Berg local->ops->remove_interface(&local->hw, &sdata->vif); 1907b7eab6fSJohannes Berg sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; 1914efc76bdSJohannes Berg trace_drv_return_void(local); 19224487981SJohannes Berg } 19324487981SJohannes Berg 19424487981SJohannes Berg static inline int drv_config(struct ieee80211_local *local, u32 changed) 19524487981SJohannes Berg { 196e1781ed3SKalle Valo int ret; 197e1781ed3SKalle Valo 198e1781ed3SKalle Valo might_sleep(); 199e1781ed3SKalle Valo 2004efc76bdSJohannes Berg trace_drv_config(local, changed); 201e1781ed3SKalle Valo ret = local->ops->config(&local->hw, changed); 2024efc76bdSJohannes Berg trace_drv_return_int(local, ret); 2030a2b8bb2SJohannes Berg return ret; 20424487981SJohannes Berg } 20524487981SJohannes Berg 20624487981SJohannes Berg static inline void drv_bss_info_changed(struct ieee80211_local *local, 20712375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 20824487981SJohannes Berg struct ieee80211_bss_conf *info, 20924487981SJohannes Berg u32 changed) 21024487981SJohannes Berg { 211e1781ed3SKalle Valo might_sleep(); 212e1781ed3SKalle Valo 2135bbe754dSJohannes Berg if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON | 214b8dc1a35SJohannes Berg BSS_CHANGED_BEACON_ENABLED) && 215b8dc1a35SJohannes Berg sdata->vif.type != NL80211_IFTYPE_AP && 216b8dc1a35SJohannes Berg sdata->vif.type != NL80211_IFTYPE_ADHOC && 217239281f8SRostislav Lisovy sdata->vif.type != NL80211_IFTYPE_MESH_POINT && 218239281f8SRostislav Lisovy sdata->vif.type != NL80211_IFTYPE_OCB)) 2195bbe754dSJohannes Berg return; 2205bbe754dSJohannes Berg 2215bbe754dSJohannes Berg if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || 2225bbe754dSJohannes Berg sdata->vif.type == NL80211_IFTYPE_MONITOR)) 2235bbe754dSJohannes Berg return; 224b8dc1a35SJohannes Berg 225f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 226f6837ba8SJohannes Berg return; 2277b7eab6fSJohannes Berg 2284efc76bdSJohannes Berg trace_drv_bss_info_changed(local, sdata, info, changed); 22924487981SJohannes Berg if (local->ops->bss_info_changed) 23012375ef9SJohannes Berg local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); 2314efc76bdSJohannes Berg trace_drv_return_void(local); 23224487981SJohannes Berg } 23324487981SJohannes Berg 2343ac64beeSJohannes Berg static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 23522bedad3SJiri Pirko struct netdev_hw_addr_list *mc_list) 23624487981SJohannes Berg { 2373ac64beeSJohannes Berg u64 ret = 0; 2383ac64beeSJohannes Berg 2394efc76bdSJohannes Berg trace_drv_prepare_multicast(local, mc_list->count); 2404efc76bdSJohannes Berg 2413ac64beeSJohannes Berg if (local->ops->prepare_multicast) 24222bedad3SJiri Pirko ret = local->ops->prepare_multicast(&local->hw, mc_list); 2433ac64beeSJohannes Berg 2444efc76bdSJohannes Berg trace_drv_return_u64(local, ret); 2453ac64beeSJohannes Berg 2463ac64beeSJohannes Berg return ret; 2473ac64beeSJohannes Berg } 2483ac64beeSJohannes Berg 2493ac64beeSJohannes Berg static inline void drv_configure_filter(struct ieee80211_local *local, 2503ac64beeSJohannes Berg unsigned int changed_flags, 2513ac64beeSJohannes Berg unsigned int *total_flags, 2523ac64beeSJohannes Berg u64 multicast) 2533ac64beeSJohannes Berg { 2543ac64beeSJohannes Berg might_sleep(); 2553ac64beeSJohannes Berg 2560a2b8bb2SJohannes Berg trace_drv_configure_filter(local, changed_flags, total_flags, 2573ac64beeSJohannes Berg multicast); 2584efc76bdSJohannes Berg local->ops->configure_filter(&local->hw, changed_flags, total_flags, 2594efc76bdSJohannes Berg multicast); 2604efc76bdSJohannes Berg trace_drv_return_void(local); 26124487981SJohannes Berg } 26224487981SJohannes Berg 263*1b09b556SAndrei Otcheretianski static inline void drv_config_iface_filter(struct ieee80211_local *local, 264*1b09b556SAndrei Otcheretianski struct ieee80211_sub_if_data *sdata, 265*1b09b556SAndrei Otcheretianski unsigned int filter_flags, 266*1b09b556SAndrei Otcheretianski unsigned int changed_flags) 267*1b09b556SAndrei Otcheretianski { 268*1b09b556SAndrei Otcheretianski might_sleep(); 269*1b09b556SAndrei Otcheretianski 270*1b09b556SAndrei Otcheretianski trace_drv_config_iface_filter(local, sdata, filter_flags, 271*1b09b556SAndrei Otcheretianski changed_flags); 272*1b09b556SAndrei Otcheretianski if (local->ops->config_iface_filter) 273*1b09b556SAndrei Otcheretianski local->ops->config_iface_filter(&local->hw, &sdata->vif, 274*1b09b556SAndrei Otcheretianski filter_flags, 275*1b09b556SAndrei Otcheretianski changed_flags); 276*1b09b556SAndrei Otcheretianski trace_drv_return_void(local); 277*1b09b556SAndrei Otcheretianski } 278*1b09b556SAndrei Otcheretianski 27924487981SJohannes Berg static inline int drv_set_tim(struct ieee80211_local *local, 28024487981SJohannes Berg struct ieee80211_sta *sta, bool set) 28124487981SJohannes Berg { 2820a2b8bb2SJohannes Berg int ret = 0; 2834efc76bdSJohannes Berg trace_drv_set_tim(local, sta, set); 28424487981SJohannes Berg if (local->ops->set_tim) 2850a2b8bb2SJohannes Berg ret = local->ops->set_tim(&local->hw, sta, set); 2864efc76bdSJohannes Berg trace_drv_return_int(local, ret); 2870a2b8bb2SJohannes Berg return ret; 28824487981SJohannes Berg } 28924487981SJohannes Berg 29024487981SJohannes Berg static inline int drv_set_key(struct ieee80211_local *local, 29112375ef9SJohannes Berg enum set_key_cmd cmd, 29212375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 29324487981SJohannes Berg struct ieee80211_sta *sta, 29424487981SJohannes Berg struct ieee80211_key_conf *key) 29524487981SJohannes Berg { 296e1781ed3SKalle Valo int ret; 297e1781ed3SKalle Valo 298e1781ed3SKalle Valo might_sleep(); 299e1781ed3SKalle Valo 300077f4939SJohannes Berg sdata = get_bss_sdata(sdata); 301f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 302f6837ba8SJohannes Berg return -EIO; 3037b7eab6fSJohannes Berg 3044efc76bdSJohannes Berg trace_drv_set_key(local, cmd, sdata, sta, key); 305e1781ed3SKalle Valo ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); 3064efc76bdSJohannes Berg trace_drv_return_int(local, ret); 3070a2b8bb2SJohannes Berg return ret; 30824487981SJohannes Berg } 30924487981SJohannes Berg 31024487981SJohannes Berg static inline void drv_update_tkip_key(struct ieee80211_local *local, 311b3fbdcf4SJohannes Berg struct ieee80211_sub_if_data *sdata, 31224487981SJohannes Berg struct ieee80211_key_conf *conf, 313b3fbdcf4SJohannes Berg struct sta_info *sta, u32 iv32, 31424487981SJohannes Berg u16 *phase1key) 31524487981SJohannes Berg { 316b3fbdcf4SJohannes Berg struct ieee80211_sta *ista = NULL; 317b3fbdcf4SJohannes Berg 318b3fbdcf4SJohannes Berg if (sta) 319b3fbdcf4SJohannes Berg ista = &sta->sta; 320b3fbdcf4SJohannes Berg 321077f4939SJohannes Berg sdata = get_bss_sdata(sdata); 322f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 323f6837ba8SJohannes Berg return; 3247b7eab6fSJohannes Berg 3254efc76bdSJohannes Berg trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); 32624487981SJohannes Berg if (local->ops->update_tkip_key) 327b3fbdcf4SJohannes Berg local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, 328b3fbdcf4SJohannes Berg ista, iv32, phase1key); 3294efc76bdSJohannes Berg trace_drv_return_void(local); 33024487981SJohannes Berg } 33124487981SJohannes Berg 33224487981SJohannes Berg static inline int drv_hw_scan(struct ieee80211_local *local, 333a060bbfeSJohannes Berg struct ieee80211_sub_if_data *sdata, 334c56ef672SDavid Spinadel struct ieee80211_scan_request *req) 33524487981SJohannes Berg { 336e1781ed3SKalle Valo int ret; 337e1781ed3SKalle Valo 338e1781ed3SKalle Valo might_sleep(); 339e1781ed3SKalle Valo 340f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 341f6837ba8SJohannes Berg return -EIO; 3427b7eab6fSJohannes Berg 34379f460caSLuciano Coelho trace_drv_hw_scan(local, sdata); 344a060bbfeSJohannes Berg ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); 3454efc76bdSJohannes Berg trace_drv_return_int(local, ret); 3460a2b8bb2SJohannes Berg return ret; 34724487981SJohannes Berg } 34824487981SJohannes Berg 349b856439bSEliad Peller static inline void drv_cancel_hw_scan(struct ieee80211_local *local, 350b856439bSEliad Peller struct ieee80211_sub_if_data *sdata) 351b856439bSEliad Peller { 352b856439bSEliad Peller might_sleep(); 353b856439bSEliad Peller 354f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 355f6837ba8SJohannes Berg return; 3567b7eab6fSJohannes Berg 357b856439bSEliad Peller trace_drv_cancel_hw_scan(local, sdata); 358b856439bSEliad Peller local->ops->cancel_hw_scan(&local->hw, &sdata->vif); 359b856439bSEliad Peller trace_drv_return_void(local); 360b856439bSEliad Peller } 361b856439bSEliad Peller 36279f460caSLuciano Coelho static inline int 36379f460caSLuciano Coelho drv_sched_scan_start(struct ieee80211_local *local, 36479f460caSLuciano Coelho struct ieee80211_sub_if_data *sdata, 36579f460caSLuciano Coelho struct cfg80211_sched_scan_request *req, 366633e2713SDavid Spinadel struct ieee80211_scan_ies *ies) 36779f460caSLuciano Coelho { 36879f460caSLuciano Coelho int ret; 36979f460caSLuciano Coelho 37079f460caSLuciano Coelho might_sleep(); 37179f460caSLuciano Coelho 372f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 373f6837ba8SJohannes Berg return -EIO; 3747b7eab6fSJohannes Berg 37579f460caSLuciano Coelho trace_drv_sched_scan_start(local, sdata); 37679f460caSLuciano Coelho ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, 37779f460caSLuciano Coelho req, ies); 37879f460caSLuciano Coelho trace_drv_return_int(local, ret); 37979f460caSLuciano Coelho return ret; 38079f460caSLuciano Coelho } 38179f460caSLuciano Coelho 38237e3308cSJohannes Berg static inline int drv_sched_scan_stop(struct ieee80211_local *local, 38379f460caSLuciano Coelho struct ieee80211_sub_if_data *sdata) 38479f460caSLuciano Coelho { 38537e3308cSJohannes Berg int ret; 38637e3308cSJohannes Berg 38779f460caSLuciano Coelho might_sleep(); 38879f460caSLuciano Coelho 389f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 390f6837ba8SJohannes Berg return -EIO; 3917b7eab6fSJohannes Berg 39279f460caSLuciano Coelho trace_drv_sched_scan_stop(local, sdata); 39337e3308cSJohannes Berg ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); 39437e3308cSJohannes Berg trace_drv_return_int(local, ret); 39537e3308cSJohannes Berg 39637e3308cSJohannes Berg return ret; 39779f460caSLuciano Coelho } 39879f460caSLuciano Coelho 399a344d677SJohannes Berg static inline void drv_sw_scan_start(struct ieee80211_local *local, 400a344d677SJohannes Berg struct ieee80211_sub_if_data *sdata, 401a344d677SJohannes Berg const u8 *mac_addr) 40224487981SJohannes Berg { 403e1781ed3SKalle Valo might_sleep(); 404e1781ed3SKalle Valo 405a344d677SJohannes Berg trace_drv_sw_scan_start(local, sdata, mac_addr); 40624487981SJohannes Berg if (local->ops->sw_scan_start) 407a344d677SJohannes Berg local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr); 4084efc76bdSJohannes Berg trace_drv_return_void(local); 40924487981SJohannes Berg } 41024487981SJohannes Berg 411a344d677SJohannes Berg static inline void drv_sw_scan_complete(struct ieee80211_local *local, 412a344d677SJohannes Berg struct ieee80211_sub_if_data *sdata) 41324487981SJohannes Berg { 414e1781ed3SKalle Valo might_sleep(); 415e1781ed3SKalle Valo 416a344d677SJohannes Berg trace_drv_sw_scan_complete(local, sdata); 41724487981SJohannes Berg if (local->ops->sw_scan_complete) 418a344d677SJohannes Berg local->ops->sw_scan_complete(&local->hw, &sdata->vif); 4194efc76bdSJohannes Berg trace_drv_return_void(local); 42024487981SJohannes Berg } 42124487981SJohannes Berg 42224487981SJohannes Berg static inline int drv_get_stats(struct ieee80211_local *local, 42324487981SJohannes Berg struct ieee80211_low_level_stats *stats) 42424487981SJohannes Berg { 4250a2b8bb2SJohannes Berg int ret = -EOPNOTSUPP; 4260a2b8bb2SJohannes Berg 427e1781ed3SKalle Valo might_sleep(); 428e1781ed3SKalle Valo 4290a2b8bb2SJohannes Berg if (local->ops->get_stats) 4300a2b8bb2SJohannes Berg ret = local->ops->get_stats(&local->hw, stats); 4310a2b8bb2SJohannes Berg trace_drv_get_stats(local, stats, ret); 4320a2b8bb2SJohannes Berg 4330a2b8bb2SJohannes Berg return ret; 43424487981SJohannes Berg } 43524487981SJohannes Berg 4369352c19fSJohannes Berg static inline void drv_get_key_seq(struct ieee80211_local *local, 4379352c19fSJohannes Berg struct ieee80211_key *key, 4389352c19fSJohannes Berg struct ieee80211_key_seq *seq) 43924487981SJohannes Berg { 4409352c19fSJohannes Berg if (local->ops->get_key_seq) 4419352c19fSJohannes Berg local->ops->get_key_seq(&local->hw, &key->conf, seq); 4429352c19fSJohannes Berg trace_drv_get_key_seq(local, &key->conf); 44324487981SJohannes Berg } 44424487981SJohannes Berg 445f23a4780SArik Nemtsov static inline int drv_set_frag_threshold(struct ieee80211_local *local, 446f23a4780SArik Nemtsov u32 value) 447f23a4780SArik Nemtsov { 448f23a4780SArik Nemtsov int ret = 0; 449f23a4780SArik Nemtsov 450f23a4780SArik Nemtsov might_sleep(); 451f23a4780SArik Nemtsov 452f23a4780SArik Nemtsov trace_drv_set_frag_threshold(local, value); 453f23a4780SArik Nemtsov if (local->ops->set_frag_threshold) 454f23a4780SArik Nemtsov ret = local->ops->set_frag_threshold(&local->hw, value); 455f23a4780SArik Nemtsov trace_drv_return_int(local, ret); 456f23a4780SArik Nemtsov return ret; 457f23a4780SArik Nemtsov } 458f23a4780SArik Nemtsov 45924487981SJohannes Berg static inline int drv_set_rts_threshold(struct ieee80211_local *local, 46024487981SJohannes Berg u32 value) 46124487981SJohannes Berg { 4620a2b8bb2SJohannes Berg int ret = 0; 463e1781ed3SKalle Valo 464e1781ed3SKalle Valo might_sleep(); 465e1781ed3SKalle Valo 4664efc76bdSJohannes Berg trace_drv_set_rts_threshold(local, value); 46724487981SJohannes Berg if (local->ops->set_rts_threshold) 4680a2b8bb2SJohannes Berg ret = local->ops->set_rts_threshold(&local->hw, value); 4694efc76bdSJohannes Berg trace_drv_return_int(local, ret); 4700a2b8bb2SJohannes Berg return ret; 47124487981SJohannes Berg } 47224487981SJohannes Berg 473310bc676SLukáš Turek static inline int drv_set_coverage_class(struct ieee80211_local *local, 474a4bcaf55SLorenzo Bianconi s16 value) 475310bc676SLukáš Turek { 476310bc676SLukáš Turek int ret = 0; 477310bc676SLukáš Turek might_sleep(); 478310bc676SLukáš Turek 4794efc76bdSJohannes Berg trace_drv_set_coverage_class(local, value); 480310bc676SLukáš Turek if (local->ops->set_coverage_class) 481310bc676SLukáš Turek local->ops->set_coverage_class(&local->hw, value); 482310bc676SLukáš Turek else 483310bc676SLukáš Turek ret = -EOPNOTSUPP; 484310bc676SLukáš Turek 4854efc76bdSJohannes Berg trace_drv_return_int(local, ret); 486310bc676SLukáš Turek return ret; 487310bc676SLukáš Turek } 488310bc676SLukáš Turek 48924487981SJohannes Berg static inline void drv_sta_notify(struct ieee80211_local *local, 49012375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 49124487981SJohannes Berg enum sta_notify_cmd cmd, 49224487981SJohannes Berg struct ieee80211_sta *sta) 49324487981SJohannes Berg { 494bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 495f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 496f6837ba8SJohannes Berg return; 4977b7eab6fSJohannes Berg 4984efc76bdSJohannes Berg trace_drv_sta_notify(local, sdata, cmd, sta); 49924487981SJohannes Berg if (local->ops->sta_notify) 50012375ef9SJohannes Berg local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); 5014efc76bdSJohannes Berg trace_drv_return_void(local); 50224487981SJohannes Berg } 50324487981SJohannes Berg 50434e89507SJohannes Berg static inline int drv_sta_add(struct ieee80211_local *local, 50534e89507SJohannes Berg struct ieee80211_sub_if_data *sdata, 50634e89507SJohannes Berg struct ieee80211_sta *sta) 50734e89507SJohannes Berg { 50834e89507SJohannes Berg int ret = 0; 50934e89507SJohannes Berg 51034e89507SJohannes Berg might_sleep(); 51134e89507SJohannes Berg 512bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 513f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 514f6837ba8SJohannes Berg return -EIO; 5157b7eab6fSJohannes Berg 5164efc76bdSJohannes Berg trace_drv_sta_add(local, sdata, sta); 51734e89507SJohannes Berg if (local->ops->sta_add) 51834e89507SJohannes Berg ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); 51934e89507SJohannes Berg 5204efc76bdSJohannes Berg trace_drv_return_int(local, ret); 52134e89507SJohannes Berg 52234e89507SJohannes Berg return ret; 52334e89507SJohannes Berg } 52434e89507SJohannes Berg 52534e89507SJohannes Berg static inline void drv_sta_remove(struct ieee80211_local *local, 52634e89507SJohannes Berg struct ieee80211_sub_if_data *sdata, 52734e89507SJohannes Berg struct ieee80211_sta *sta) 52834e89507SJohannes Berg { 52934e89507SJohannes Berg might_sleep(); 53034e89507SJohannes Berg 531bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 532f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 533f6837ba8SJohannes Berg return; 5347b7eab6fSJohannes Berg 5354efc76bdSJohannes Berg trace_drv_sta_remove(local, sdata, sta); 53634e89507SJohannes Berg if (local->ops->sta_remove) 53734e89507SJohannes Berg local->ops->sta_remove(&local->hw, &sdata->vif, sta); 53834e89507SJohannes Berg 5394efc76bdSJohannes Berg trace_drv_return_void(local); 54034e89507SJohannes Berg } 54134e89507SJohannes Berg 54277d2ece6SSujith Manoharan #ifdef CONFIG_MAC80211_DEBUGFS 54377d2ece6SSujith Manoharan static inline void drv_sta_add_debugfs(struct ieee80211_local *local, 54477d2ece6SSujith Manoharan struct ieee80211_sub_if_data *sdata, 54577d2ece6SSujith Manoharan struct ieee80211_sta *sta, 54677d2ece6SSujith Manoharan struct dentry *dir) 54777d2ece6SSujith Manoharan { 54877d2ece6SSujith Manoharan might_sleep(); 54977d2ece6SSujith Manoharan 55077d2ece6SSujith Manoharan sdata = get_bss_sdata(sdata); 551f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 552f6837ba8SJohannes Berg return; 55377d2ece6SSujith Manoharan 55477d2ece6SSujith Manoharan if (local->ops->sta_add_debugfs) 55577d2ece6SSujith Manoharan local->ops->sta_add_debugfs(&local->hw, &sdata->vif, 55677d2ece6SSujith Manoharan sta, dir); 55777d2ece6SSujith Manoharan } 55877d2ece6SSujith Manoharan 55977d2ece6SSujith Manoharan static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, 56077d2ece6SSujith Manoharan struct ieee80211_sub_if_data *sdata, 56177d2ece6SSujith Manoharan struct ieee80211_sta *sta, 56277d2ece6SSujith Manoharan struct dentry *dir) 56377d2ece6SSujith Manoharan { 56477d2ece6SSujith Manoharan might_sleep(); 56577d2ece6SSujith Manoharan 56677d2ece6SSujith Manoharan sdata = get_bss_sdata(sdata); 56777d2ece6SSujith Manoharan check_sdata_in_driver(sdata); 56877d2ece6SSujith Manoharan 56977d2ece6SSujith Manoharan if (local->ops->sta_remove_debugfs) 57077d2ece6SSujith Manoharan local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, 57177d2ece6SSujith Manoharan sta, dir); 57277d2ece6SSujith Manoharan } 57377d2ece6SSujith Manoharan #endif 57477d2ece6SSujith Manoharan 5756a9d1b91SJohannes Berg static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, 5766a9d1b91SJohannes Berg struct ieee80211_sub_if_data *sdata, 5776a9d1b91SJohannes Berg struct sta_info *sta) 5786a9d1b91SJohannes Berg { 5796a9d1b91SJohannes Berg might_sleep(); 5806a9d1b91SJohannes Berg 5816a9d1b91SJohannes Berg sdata = get_bss_sdata(sdata); 582f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 583f6837ba8SJohannes Berg return; 5846a9d1b91SJohannes Berg 5856a9d1b91SJohannes Berg trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); 5866a9d1b91SJohannes Berg if (local->ops->sta_pre_rcu_remove) 5876a9d1b91SJohannes Berg local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif, 5886a9d1b91SJohannes Berg &sta->sta); 5896a9d1b91SJohannes Berg trace_drv_return_void(local); 5906a9d1b91SJohannes Berg } 5916a9d1b91SJohannes Berg 592727da60bSDenys Vlasenko __must_check 593f09603a2SJohannes Berg int drv_sta_state(struct ieee80211_local *local, 594f09603a2SJohannes Berg struct ieee80211_sub_if_data *sdata, 595f09603a2SJohannes Berg struct sta_info *sta, 596f09603a2SJohannes Berg enum ieee80211_sta_state old_state, 597727da60bSDenys Vlasenko enum ieee80211_sta_state new_state); 598f09603a2SJohannes Berg 5998f727ef3SJohannes Berg static inline void drv_sta_rc_update(struct ieee80211_local *local, 6008f727ef3SJohannes Berg struct ieee80211_sub_if_data *sdata, 6018f727ef3SJohannes Berg struct ieee80211_sta *sta, u32 changed) 6028f727ef3SJohannes Berg { 6038f727ef3SJohannes Berg sdata = get_bss_sdata(sdata); 604f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 605f6837ba8SJohannes Berg return; 6068f727ef3SJohannes Berg 607e687f61eSAntonio Quartulli WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && 608f68d776aSThomas Pedersen (sdata->vif.type != NL80211_IFTYPE_ADHOC && 609f68d776aSThomas Pedersen sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); 610e687f61eSAntonio Quartulli 6118f727ef3SJohannes Berg trace_drv_sta_rc_update(local, sdata, sta, changed); 6128f727ef3SJohannes Berg if (local->ops->sta_rc_update) 6138f727ef3SJohannes Berg local->ops->sta_rc_update(&local->hw, &sdata->vif, 6148f727ef3SJohannes Berg sta, changed); 6158f727ef3SJohannes Berg 6168f727ef3SJohannes Berg trace_drv_return_void(local); 6178f727ef3SJohannes Berg } 6188f727ef3SJohannes Berg 619f815e2b3SJohannes Berg static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, 620f815e2b3SJohannes Berg struct ieee80211_sub_if_data *sdata, 621f815e2b3SJohannes Berg struct ieee80211_sta *sta) 622f815e2b3SJohannes Berg { 623f815e2b3SJohannes Berg sdata = get_bss_sdata(sdata); 624f815e2b3SJohannes Berg if (!check_sdata_in_driver(sdata)) 625f815e2b3SJohannes Berg return; 626f815e2b3SJohannes Berg 627f815e2b3SJohannes Berg trace_drv_sta_rate_tbl_update(local, sdata, sta); 628f815e2b3SJohannes Berg if (local->ops->sta_rate_tbl_update) 629f815e2b3SJohannes Berg local->ops->sta_rate_tbl_update(&local->hw, &sdata->vif, sta); 630f815e2b3SJohannes Berg 631f815e2b3SJohannes Berg trace_drv_return_void(local); 632f815e2b3SJohannes Berg } 633f815e2b3SJohannes Berg 6342b9a7e1bSJohannes Berg static inline void drv_sta_statistics(struct ieee80211_local *local, 6352b9a7e1bSJohannes Berg struct ieee80211_sub_if_data *sdata, 6362b9a7e1bSJohannes Berg struct ieee80211_sta *sta, 6372b9a7e1bSJohannes Berg struct station_info *sinfo) 6382b9a7e1bSJohannes Berg { 6392b9a7e1bSJohannes Berg sdata = get_bss_sdata(sdata); 6402b9a7e1bSJohannes Berg if (!check_sdata_in_driver(sdata)) 6412b9a7e1bSJohannes Berg return; 6422b9a7e1bSJohannes Berg 6432b9a7e1bSJohannes Berg trace_drv_sta_statistics(local, sdata, sta); 6442b9a7e1bSJohannes Berg if (local->ops->sta_statistics) 6452b9a7e1bSJohannes Berg local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo); 6462b9a7e1bSJohannes Berg trace_drv_return_void(local); 6472b9a7e1bSJohannes Berg } 6482b9a7e1bSJohannes Berg 649f6f3def3SEliad Peller static inline int drv_conf_tx(struct ieee80211_local *local, 650a3304b0aSJohannes Berg struct ieee80211_sub_if_data *sdata, u16 ac, 65124487981SJohannes Berg const struct ieee80211_tx_queue_params *params) 65224487981SJohannes Berg { 6530a2b8bb2SJohannes Berg int ret = -EOPNOTSUPP; 654e1781ed3SKalle Valo 655e1781ed3SKalle Valo might_sleep(); 656e1781ed3SKalle Valo 657f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 658f6837ba8SJohannes Berg return -EIO; 6597b7eab6fSJohannes Berg 660f409079bSJohannes Berg if (WARN_ONCE(params->cw_min == 0 || 661f409079bSJohannes Berg params->cw_min > params->cw_max, 662f409079bSJohannes Berg "%s: invalid CW_min/CW_max: %d/%d\n", 663f409079bSJohannes Berg sdata->name, params->cw_min, params->cw_max)) 664f409079bSJohannes Berg return -EINVAL; 665f409079bSJohannes Berg 666a3304b0aSJohannes Berg trace_drv_conf_tx(local, sdata, ac, params); 66724487981SJohannes Berg if (local->ops->conf_tx) 6688a3a3c85SEliad Peller ret = local->ops->conf_tx(&local->hw, &sdata->vif, 669a3304b0aSJohannes Berg ac, params); 6704efc76bdSJohannes Berg trace_drv_return_int(local, ret); 6710a2b8bb2SJohannes Berg return ret; 67224487981SJohannes Berg } 67324487981SJohannes Berg 67437a41b4aSEliad Peller static inline u64 drv_get_tsf(struct ieee80211_local *local, 67537a41b4aSEliad Peller struct ieee80211_sub_if_data *sdata) 67624487981SJohannes Berg { 6770a2b8bb2SJohannes Berg u64 ret = -1ULL; 678e1781ed3SKalle Valo 679e1781ed3SKalle Valo might_sleep(); 680e1781ed3SKalle Valo 681f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 682f6837ba8SJohannes Berg return ret; 6837b7eab6fSJohannes Berg 68437a41b4aSEliad Peller trace_drv_get_tsf(local, sdata); 68524487981SJohannes Berg if (local->ops->get_tsf) 68637a41b4aSEliad Peller ret = local->ops->get_tsf(&local->hw, &sdata->vif); 6874efc76bdSJohannes Berg trace_drv_return_u64(local, ret); 6880a2b8bb2SJohannes Berg return ret; 68924487981SJohannes Berg } 69024487981SJohannes Berg 69137a41b4aSEliad Peller static inline void drv_set_tsf(struct ieee80211_local *local, 69237a41b4aSEliad Peller struct ieee80211_sub_if_data *sdata, 69337a41b4aSEliad Peller u64 tsf) 69424487981SJohannes Berg { 695e1781ed3SKalle Valo might_sleep(); 696e1781ed3SKalle Valo 697f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 698f6837ba8SJohannes Berg return; 6997b7eab6fSJohannes Berg 70037a41b4aSEliad Peller trace_drv_set_tsf(local, sdata, tsf); 70124487981SJohannes Berg if (local->ops->set_tsf) 70237a41b4aSEliad Peller local->ops->set_tsf(&local->hw, &sdata->vif, tsf); 7034efc76bdSJohannes Berg trace_drv_return_void(local); 70424487981SJohannes Berg } 70524487981SJohannes Berg 70637a41b4aSEliad Peller static inline void drv_reset_tsf(struct ieee80211_local *local, 70737a41b4aSEliad Peller struct ieee80211_sub_if_data *sdata) 70824487981SJohannes Berg { 709e1781ed3SKalle Valo might_sleep(); 710e1781ed3SKalle Valo 711f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 712f6837ba8SJohannes Berg return; 7137b7eab6fSJohannes Berg 71437a41b4aSEliad Peller trace_drv_reset_tsf(local, sdata); 71524487981SJohannes Berg if (local->ops->reset_tsf) 71637a41b4aSEliad Peller local->ops->reset_tsf(&local->hw, &sdata->vif); 7174efc76bdSJohannes Berg trace_drv_return_void(local); 71824487981SJohannes Berg } 71924487981SJohannes Berg 72024487981SJohannes Berg static inline int drv_tx_last_beacon(struct ieee80211_local *local) 72124487981SJohannes Berg { 72202582e9bSMasanari Iida int ret = 0; /* default unsupported op for less congestion */ 723e1781ed3SKalle Valo 724e1781ed3SKalle Valo might_sleep(); 725e1781ed3SKalle Valo 7264efc76bdSJohannes Berg trace_drv_tx_last_beacon(local); 72724487981SJohannes Berg if (local->ops->tx_last_beacon) 7280a2b8bb2SJohannes Berg ret = local->ops->tx_last_beacon(&local->hw); 7294efc76bdSJohannes Berg trace_drv_return_int(local, ret); 7300a2b8bb2SJohannes Berg return ret; 73124487981SJohannes Berg } 73224487981SJohannes Berg 73324487981SJohannes Berg static inline int drv_ampdu_action(struct ieee80211_local *local, 73412375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 73524487981SJohannes Berg enum ieee80211_ampdu_mlme_action action, 73624487981SJohannes Berg struct ieee80211_sta *sta, u16 tid, 7370b01f030SJohannes Berg u16 *ssn, u8 buf_size) 73824487981SJohannes Berg { 7390a2b8bb2SJohannes Berg int ret = -EOPNOTSUPP; 740cfcdbde3SJohannes Berg 741cfcdbde3SJohannes Berg might_sleep(); 742cfcdbde3SJohannes Berg 743bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 744f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 745f6837ba8SJohannes Berg return -EIO; 7467b7eab6fSJohannes Berg 7470b01f030SJohannes Berg trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); 7484efc76bdSJohannes Berg 74924487981SJohannes Berg if (local->ops->ampdu_action) 75012375ef9SJohannes Berg ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, 7510b01f030SJohannes Berg sta, tid, ssn, buf_size); 75285ad181eSJohannes Berg 7534efc76bdSJohannes Berg trace_drv_return_int(local, ret); 7544efc76bdSJohannes Berg 7550a2b8bb2SJohannes Berg return ret; 75624487981SJohannes Berg } 7571f87f7d3SJohannes Berg 7581289723eSHolger Schurig static inline int drv_get_survey(struct ieee80211_local *local, int idx, 7591289723eSHolger Schurig struct survey_info *survey) 7601289723eSHolger Schurig { 7611289723eSHolger Schurig int ret = -EOPNOTSUPP; 762c466d4efSJohn W. Linville 763c466d4efSJohn W. Linville trace_drv_get_survey(local, idx, survey); 764c466d4efSJohn W. Linville 76535dd0509SHolger Schurig if (local->ops->get_survey) 7661289723eSHolger Schurig ret = local->ops->get_survey(&local->hw, idx, survey); 767c466d4efSJohn W. Linville 768c466d4efSJohn W. Linville trace_drv_return_int(local, ret); 769c466d4efSJohn W. Linville 7701289723eSHolger Schurig return ret; 7711289723eSHolger Schurig } 7721f87f7d3SJohannes Berg 7731f87f7d3SJohannes Berg static inline void drv_rfkill_poll(struct ieee80211_local *local) 7741f87f7d3SJohannes Berg { 775e1781ed3SKalle Valo might_sleep(); 776e1781ed3SKalle Valo 7771f87f7d3SJohannes Berg if (local->ops->rfkill_poll) 7781f87f7d3SJohannes Berg local->ops->rfkill_poll(&local->hw); 7791f87f7d3SJohannes Berg } 780a80f7c0bSJohannes Berg 78139ecc01dSJohannes Berg static inline void drv_flush(struct ieee80211_local *local, 78277be2c54SEmmanuel Grumbach struct ieee80211_sub_if_data *sdata, 78339ecc01dSJohannes Berg u32 queues, bool drop) 784a80f7c0bSJohannes Berg { 78577be2c54SEmmanuel Grumbach struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; 78677be2c54SEmmanuel Grumbach 787e1781ed3SKalle Valo might_sleep(); 788e1781ed3SKalle Valo 789f6837ba8SJohannes Berg if (sdata && !check_sdata_in_driver(sdata)) 790f6837ba8SJohannes Berg return; 79177be2c54SEmmanuel Grumbach 79239ecc01dSJohannes Berg trace_drv_flush(local, queues, drop); 793a80f7c0bSJohannes Berg if (local->ops->flush) 79477be2c54SEmmanuel Grumbach local->ops->flush(&local->hw, vif, queues, drop); 7954efc76bdSJohannes Berg trace_drv_return_void(local); 796a80f7c0bSJohannes Berg } 7975ce6e438SJohannes Berg 7985ce6e438SJohannes Berg static inline void drv_channel_switch(struct ieee80211_local *local, 7990f791eb4SLuciano Coelho struct ieee80211_sub_if_data *sdata, 8005ce6e438SJohannes Berg struct ieee80211_channel_switch *ch_switch) 8015ce6e438SJohannes Berg { 8025ce6e438SJohannes Berg might_sleep(); 8035ce6e438SJohannes Berg 8040f791eb4SLuciano Coelho trace_drv_channel_switch(local, sdata, ch_switch); 8050f791eb4SLuciano Coelho local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch); 8064efc76bdSJohannes Berg trace_drv_return_void(local); 8075ce6e438SJohannes Berg } 8085ce6e438SJohannes Berg 80915d96753SBruno Randolf 81015d96753SBruno Randolf static inline int drv_set_antenna(struct ieee80211_local *local, 81115d96753SBruno Randolf u32 tx_ant, u32 rx_ant) 81215d96753SBruno Randolf { 81315d96753SBruno Randolf int ret = -EOPNOTSUPP; 81415d96753SBruno Randolf might_sleep(); 81515d96753SBruno Randolf if (local->ops->set_antenna) 81615d96753SBruno Randolf ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant); 81715d96753SBruno Randolf trace_drv_set_antenna(local, tx_ant, rx_ant, ret); 81815d96753SBruno Randolf return ret; 81915d96753SBruno Randolf } 82015d96753SBruno Randolf 82115d96753SBruno Randolf static inline int drv_get_antenna(struct ieee80211_local *local, 82215d96753SBruno Randolf u32 *tx_ant, u32 *rx_ant) 82315d96753SBruno Randolf { 82415d96753SBruno Randolf int ret = -EOPNOTSUPP; 82515d96753SBruno Randolf might_sleep(); 82615d96753SBruno Randolf if (local->ops->get_antenna) 82715d96753SBruno Randolf ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant); 82815d96753SBruno Randolf trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret); 82915d96753SBruno Randolf return ret; 83015d96753SBruno Randolf } 83115d96753SBruno Randolf 83221f83589SJohannes Berg static inline int drv_remain_on_channel(struct ieee80211_local *local, 83349884568SEliad Peller struct ieee80211_sub_if_data *sdata, 83421f83589SJohannes Berg struct ieee80211_channel *chan, 835d339d5caSIlan Peer unsigned int duration, 836d339d5caSIlan Peer enum ieee80211_roc_type type) 83721f83589SJohannes Berg { 83821f83589SJohannes Berg int ret; 83921f83589SJohannes Berg 84021f83589SJohannes Berg might_sleep(); 84121f83589SJohannes Berg 842d339d5caSIlan Peer trace_drv_remain_on_channel(local, sdata, chan, duration, type); 84349884568SEliad Peller ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, 844d339d5caSIlan Peer chan, duration, type); 84521f83589SJohannes Berg trace_drv_return_int(local, ret); 84621f83589SJohannes Berg 84721f83589SJohannes Berg return ret; 84821f83589SJohannes Berg } 84921f83589SJohannes Berg 85021f83589SJohannes Berg static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local) 85121f83589SJohannes Berg { 85221f83589SJohannes Berg int ret; 85321f83589SJohannes Berg 85421f83589SJohannes Berg might_sleep(); 85521f83589SJohannes Berg 85621f83589SJohannes Berg trace_drv_cancel_remain_on_channel(local); 85721f83589SJohannes Berg ret = local->ops->cancel_remain_on_channel(&local->hw); 85821f83589SJohannes Berg trace_drv_return_int(local, ret); 85921f83589SJohannes Berg 86021f83589SJohannes Berg return ret; 86121f83589SJohannes Berg } 86221f83589SJohannes Berg 86338c09159SJohn W. Linville static inline int drv_set_ringparam(struct ieee80211_local *local, 86438c09159SJohn W. Linville u32 tx, u32 rx) 86538c09159SJohn W. Linville { 86638c09159SJohn W. Linville int ret = -ENOTSUPP; 86738c09159SJohn W. Linville 86838c09159SJohn W. Linville might_sleep(); 86938c09159SJohn W. Linville 87038c09159SJohn W. Linville trace_drv_set_ringparam(local, tx, rx); 87138c09159SJohn W. Linville if (local->ops->set_ringparam) 87238c09159SJohn W. Linville ret = local->ops->set_ringparam(&local->hw, tx, rx); 87338c09159SJohn W. Linville trace_drv_return_int(local, ret); 87438c09159SJohn W. Linville 87538c09159SJohn W. Linville return ret; 87638c09159SJohn W. Linville } 87738c09159SJohn W. Linville 87838c09159SJohn W. Linville static inline void drv_get_ringparam(struct ieee80211_local *local, 87938c09159SJohn W. Linville u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) 88038c09159SJohn W. Linville { 88138c09159SJohn W. Linville might_sleep(); 88238c09159SJohn W. Linville 88338c09159SJohn W. Linville trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max); 88438c09159SJohn W. Linville if (local->ops->get_ringparam) 88538c09159SJohn W. Linville local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max); 88638c09159SJohn W. Linville trace_drv_return_void(local); 88738c09159SJohn W. Linville } 88838c09159SJohn W. Linville 889e8306f98SVivek Natarajan static inline bool drv_tx_frames_pending(struct ieee80211_local *local) 890e8306f98SVivek Natarajan { 891e8306f98SVivek Natarajan bool ret = false; 892e8306f98SVivek Natarajan 893e8306f98SVivek Natarajan might_sleep(); 894e8306f98SVivek Natarajan 895e8306f98SVivek Natarajan trace_drv_tx_frames_pending(local); 896e8306f98SVivek Natarajan if (local->ops->tx_frames_pending) 897e8306f98SVivek Natarajan ret = local->ops->tx_frames_pending(&local->hw); 898e8306f98SVivek Natarajan trace_drv_return_bool(local, ret); 899e8306f98SVivek Natarajan 900e8306f98SVivek Natarajan return ret; 901e8306f98SVivek Natarajan } 902bdbfd6b5SSujith Manoharan 903bdbfd6b5SSujith Manoharan static inline int drv_set_bitrate_mask(struct ieee80211_local *local, 904bdbfd6b5SSujith Manoharan struct ieee80211_sub_if_data *sdata, 905bdbfd6b5SSujith Manoharan const struct cfg80211_bitrate_mask *mask) 906bdbfd6b5SSujith Manoharan { 907bdbfd6b5SSujith Manoharan int ret = -EOPNOTSUPP; 908bdbfd6b5SSujith Manoharan 909bdbfd6b5SSujith Manoharan might_sleep(); 910bdbfd6b5SSujith Manoharan 911f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 912f6837ba8SJohannes Berg return -EIO; 9137b7eab6fSJohannes Berg 914bdbfd6b5SSujith Manoharan trace_drv_set_bitrate_mask(local, sdata, mask); 915bdbfd6b5SSujith Manoharan if (local->ops->set_bitrate_mask) 916bdbfd6b5SSujith Manoharan ret = local->ops->set_bitrate_mask(&local->hw, 917bdbfd6b5SSujith Manoharan &sdata->vif, mask); 918bdbfd6b5SSujith Manoharan trace_drv_return_int(local, ret); 919bdbfd6b5SSujith Manoharan 920bdbfd6b5SSujith Manoharan return ret; 921bdbfd6b5SSujith Manoharan } 922bdbfd6b5SSujith Manoharan 923c68f4b89SJohannes Berg static inline void drv_set_rekey_data(struct ieee80211_local *local, 924c68f4b89SJohannes Berg struct ieee80211_sub_if_data *sdata, 925c68f4b89SJohannes Berg struct cfg80211_gtk_rekey_data *data) 926c68f4b89SJohannes Berg { 927f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 928f6837ba8SJohannes Berg return; 9297b7eab6fSJohannes Berg 930c68f4b89SJohannes Berg trace_drv_set_rekey_data(local, sdata, data); 931c68f4b89SJohannes Berg if (local->ops->set_rekey_data) 932c68f4b89SJohannes Berg local->ops->set_rekey_data(&local->hw, &sdata->vif, data); 933c68f4b89SJohannes Berg trace_drv_return_void(local); 934c68f4b89SJohannes Berg } 935c68f4b89SJohannes Berg 936a8182929SEmmanuel Grumbach static inline void drv_event_callback(struct ieee80211_local *local, 937887da917SEmmanuel Grumbach struct ieee80211_sub_if_data *sdata, 938a8182929SEmmanuel Grumbach const struct ieee80211_event *event) 939615f7b9bSMeenakshi Venkataraman { 940a8182929SEmmanuel Grumbach trace_drv_event_callback(local, sdata, event); 941a8182929SEmmanuel Grumbach if (local->ops->event_callback) 942a8182929SEmmanuel Grumbach local->ops->event_callback(&local->hw, &sdata->vif, event); 943615f7b9bSMeenakshi Venkataraman trace_drv_return_void(local); 944615f7b9bSMeenakshi Venkataraman } 9454049e09aSJohannes Berg 9464049e09aSJohannes Berg static inline void 9474049e09aSJohannes Berg drv_release_buffered_frames(struct ieee80211_local *local, 9484049e09aSJohannes Berg struct sta_info *sta, u16 tids, int num_frames, 9494049e09aSJohannes Berg enum ieee80211_frame_release_type reason, 9504049e09aSJohannes Berg bool more_data) 9514049e09aSJohannes Berg { 9524049e09aSJohannes Berg trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames, 9534049e09aSJohannes Berg reason, more_data); 9544049e09aSJohannes Berg if (local->ops->release_buffered_frames) 9554049e09aSJohannes Berg local->ops->release_buffered_frames(&local->hw, &sta->sta, tids, 9564049e09aSJohannes Berg num_frames, reason, 9574049e09aSJohannes Berg more_data); 9584049e09aSJohannes Berg trace_drv_return_void(local); 9594049e09aSJohannes Berg } 96040b96408SJohannes Berg 96140b96408SJohannes Berg static inline void 96240b96408SJohannes Berg drv_allow_buffered_frames(struct ieee80211_local *local, 96340b96408SJohannes Berg struct sta_info *sta, u16 tids, int num_frames, 96440b96408SJohannes Berg enum ieee80211_frame_release_type reason, 96540b96408SJohannes Berg bool more_data) 96640b96408SJohannes Berg { 96740b96408SJohannes Berg trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames, 96840b96408SJohannes Berg reason, more_data); 96940b96408SJohannes Berg if (local->ops->allow_buffered_frames) 97040b96408SJohannes Berg local->ops->allow_buffered_frames(&local->hw, &sta->sta, 97140b96408SJohannes Berg tids, num_frames, reason, 97240b96408SJohannes Berg more_data); 97340b96408SJohannes Berg trace_drv_return_void(local); 97440b96408SJohannes Berg } 97566572cfcSVictor Goldenshtein 976a1845fc7SJohannes Berg static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, 977a1845fc7SJohannes Berg struct ieee80211_sub_if_data *sdata) 978a1845fc7SJohannes Berg { 979a1845fc7SJohannes Berg might_sleep(); 980a1845fc7SJohannes Berg 981f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 982f6837ba8SJohannes Berg return; 983a1845fc7SJohannes Berg WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); 984a1845fc7SJohannes Berg 985a1845fc7SJohannes Berg trace_drv_mgd_prepare_tx(local, sdata); 986a1845fc7SJohannes Berg if (local->ops->mgd_prepare_tx) 987a1845fc7SJohannes Berg local->ops->mgd_prepare_tx(&local->hw, &sdata->vif); 988a1845fc7SJohannes Berg trace_drv_return_void(local); 989a1845fc7SJohannes Berg } 990c3645eacSMichal Kazior 991ee10f2c7SArik Nemtsov static inline void 992ee10f2c7SArik Nemtsov drv_mgd_protect_tdls_discover(struct ieee80211_local *local, 993ee10f2c7SArik Nemtsov struct ieee80211_sub_if_data *sdata) 994ee10f2c7SArik Nemtsov { 995ee10f2c7SArik Nemtsov might_sleep(); 996ee10f2c7SArik Nemtsov 997ee10f2c7SArik Nemtsov if (!check_sdata_in_driver(sdata)) 998ee10f2c7SArik Nemtsov return; 999ee10f2c7SArik Nemtsov WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); 1000ee10f2c7SArik Nemtsov 1001ee10f2c7SArik Nemtsov trace_drv_mgd_protect_tdls_discover(local, sdata); 1002ee10f2c7SArik Nemtsov if (local->ops->mgd_protect_tdls_discover) 1003ee10f2c7SArik Nemtsov local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif); 1004ee10f2c7SArik Nemtsov trace_drv_return_void(local); 1005ee10f2c7SArik Nemtsov } 1006ee10f2c7SArik Nemtsov 1007c3645eacSMichal Kazior static inline int drv_add_chanctx(struct ieee80211_local *local, 1008c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1009c3645eacSMichal Kazior { 1010c3645eacSMichal Kazior int ret = -EOPNOTSUPP; 1011c3645eacSMichal Kazior 1012c3645eacSMichal Kazior trace_drv_add_chanctx(local, ctx); 1013c3645eacSMichal Kazior if (local->ops->add_chanctx) 1014c3645eacSMichal Kazior ret = local->ops->add_chanctx(&local->hw, &ctx->conf); 1015c3645eacSMichal Kazior trace_drv_return_int(local, ret); 10168a61af65SJohannes Berg if (!ret) 10178a61af65SJohannes Berg ctx->driver_present = true; 1018c3645eacSMichal Kazior 1019c3645eacSMichal Kazior return ret; 1020c3645eacSMichal Kazior } 1021c3645eacSMichal Kazior 1022c3645eacSMichal Kazior static inline void drv_remove_chanctx(struct ieee80211_local *local, 1023c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1024c3645eacSMichal Kazior { 1025f6837ba8SJohannes Berg if (WARN_ON(!ctx->driver_present)) 1026f6837ba8SJohannes Berg return; 1027f6837ba8SJohannes Berg 1028c3645eacSMichal Kazior trace_drv_remove_chanctx(local, ctx); 1029c3645eacSMichal Kazior if (local->ops->remove_chanctx) 1030c3645eacSMichal Kazior local->ops->remove_chanctx(&local->hw, &ctx->conf); 1031c3645eacSMichal Kazior trace_drv_return_void(local); 10328a61af65SJohannes Berg ctx->driver_present = false; 1033c3645eacSMichal Kazior } 1034c3645eacSMichal Kazior 1035c3645eacSMichal Kazior static inline void drv_change_chanctx(struct ieee80211_local *local, 1036c3645eacSMichal Kazior struct ieee80211_chanctx *ctx, 1037c3645eacSMichal Kazior u32 changed) 1038c3645eacSMichal Kazior { 1039c3645eacSMichal Kazior trace_drv_change_chanctx(local, ctx, changed); 10408a61af65SJohannes Berg if (local->ops->change_chanctx) { 10418a61af65SJohannes Berg WARN_ON_ONCE(!ctx->driver_present); 1042c3645eacSMichal Kazior local->ops->change_chanctx(&local->hw, &ctx->conf, changed); 10438a61af65SJohannes Berg } 1044c3645eacSMichal Kazior trace_drv_return_void(local); 1045c3645eacSMichal Kazior } 1046c3645eacSMichal Kazior 1047c3645eacSMichal Kazior static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, 1048c3645eacSMichal Kazior struct ieee80211_sub_if_data *sdata, 1049c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1050c3645eacSMichal Kazior { 1051c3645eacSMichal Kazior int ret = 0; 1052c3645eacSMichal Kazior 1053f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1054f6837ba8SJohannes Berg return -EIO; 1055c3645eacSMichal Kazior 1056c3645eacSMichal Kazior trace_drv_assign_vif_chanctx(local, sdata, ctx); 10578a61af65SJohannes Berg if (local->ops->assign_vif_chanctx) { 10588a61af65SJohannes Berg WARN_ON_ONCE(!ctx->driver_present); 1059c3645eacSMichal Kazior ret = local->ops->assign_vif_chanctx(&local->hw, 1060c3645eacSMichal Kazior &sdata->vif, 1061c3645eacSMichal Kazior &ctx->conf); 10628a61af65SJohannes Berg } 1063c3645eacSMichal Kazior trace_drv_return_int(local, ret); 1064c3645eacSMichal Kazior 1065c3645eacSMichal Kazior return ret; 1066c3645eacSMichal Kazior } 1067c3645eacSMichal Kazior 1068c3645eacSMichal Kazior static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, 1069c3645eacSMichal Kazior struct ieee80211_sub_if_data *sdata, 1070c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1071c3645eacSMichal Kazior { 1072f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1073f6837ba8SJohannes Berg return; 1074c3645eacSMichal Kazior 1075c3645eacSMichal Kazior trace_drv_unassign_vif_chanctx(local, sdata, ctx); 10768a61af65SJohannes Berg if (local->ops->unassign_vif_chanctx) { 10778a61af65SJohannes Berg WARN_ON_ONCE(!ctx->driver_present); 1078c3645eacSMichal Kazior local->ops->unassign_vif_chanctx(&local->hw, 1079c3645eacSMichal Kazior &sdata->vif, 1080c3645eacSMichal Kazior &ctx->conf); 10818a61af65SJohannes Berg } 1082c3645eacSMichal Kazior trace_drv_return_void(local); 1083c3645eacSMichal Kazior } 1084c3645eacSMichal Kazior 10851a5f0c13SLuciano Coelho static inline int 10861a5f0c13SLuciano Coelho drv_switch_vif_chanctx(struct ieee80211_local *local, 10871a5f0c13SLuciano Coelho struct ieee80211_vif_chanctx_switch *vifs, 10881a5f0c13SLuciano Coelho int n_vifs, 10891a5f0c13SLuciano Coelho enum ieee80211_chanctx_switch_mode mode) 10901a5f0c13SLuciano Coelho { 10911a5f0c13SLuciano Coelho int ret = 0; 10921a5f0c13SLuciano Coelho int i; 10931a5f0c13SLuciano Coelho 10941a5f0c13SLuciano Coelho if (!local->ops->switch_vif_chanctx) 10951a5f0c13SLuciano Coelho return -EOPNOTSUPP; 10961a5f0c13SLuciano Coelho 10971a5f0c13SLuciano Coelho for (i = 0; i < n_vifs; i++) { 10981a5f0c13SLuciano Coelho struct ieee80211_chanctx *new_ctx = 10991a5f0c13SLuciano Coelho container_of(vifs[i].new_ctx, 11001a5f0c13SLuciano Coelho struct ieee80211_chanctx, 11011a5f0c13SLuciano Coelho conf); 11021a5f0c13SLuciano Coelho struct ieee80211_chanctx *old_ctx = 11031a5f0c13SLuciano Coelho container_of(vifs[i].old_ctx, 11041a5f0c13SLuciano Coelho struct ieee80211_chanctx, 11051a5f0c13SLuciano Coelho conf); 11061a5f0c13SLuciano Coelho 11071a5f0c13SLuciano Coelho WARN_ON_ONCE(!old_ctx->driver_present); 11081a5f0c13SLuciano Coelho WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS && 11091a5f0c13SLuciano Coelho new_ctx->driver_present) || 11101a5f0c13SLuciano Coelho (mode == CHANCTX_SWMODE_REASSIGN_VIF && 11111a5f0c13SLuciano Coelho !new_ctx->driver_present)); 11121a5f0c13SLuciano Coelho } 11131a5f0c13SLuciano Coelho 11141a5f0c13SLuciano Coelho trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode); 11151a5f0c13SLuciano Coelho ret = local->ops->switch_vif_chanctx(&local->hw, 11161a5f0c13SLuciano Coelho vifs, n_vifs, mode); 11171a5f0c13SLuciano Coelho trace_drv_return_int(local, ret); 11181a5f0c13SLuciano Coelho 11191a5f0c13SLuciano Coelho if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { 11201a5f0c13SLuciano Coelho for (i = 0; i < n_vifs; i++) { 11211a5f0c13SLuciano Coelho struct ieee80211_chanctx *new_ctx = 11221a5f0c13SLuciano Coelho container_of(vifs[i].new_ctx, 11231a5f0c13SLuciano Coelho struct ieee80211_chanctx, 11241a5f0c13SLuciano Coelho conf); 11251a5f0c13SLuciano Coelho struct ieee80211_chanctx *old_ctx = 11261a5f0c13SLuciano Coelho container_of(vifs[i].old_ctx, 11271a5f0c13SLuciano Coelho struct ieee80211_chanctx, 11281a5f0c13SLuciano Coelho conf); 11291a5f0c13SLuciano Coelho 11301a5f0c13SLuciano Coelho new_ctx->driver_present = true; 11311a5f0c13SLuciano Coelho old_ctx->driver_present = false; 11321a5f0c13SLuciano Coelho } 11331a5f0c13SLuciano Coelho } 11341a5f0c13SLuciano Coelho 11351a5f0c13SLuciano Coelho return ret; 11361a5f0c13SLuciano Coelho } 11371a5f0c13SLuciano Coelho 11381041638fSJohannes Berg static inline int drv_start_ap(struct ieee80211_local *local, 11391041638fSJohannes Berg struct ieee80211_sub_if_data *sdata) 11401041638fSJohannes Berg { 11411041638fSJohannes Berg int ret = 0; 11421041638fSJohannes Berg 1143f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1144f6837ba8SJohannes Berg return -EIO; 11451041638fSJohannes Berg 11461041638fSJohannes Berg trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); 11471041638fSJohannes Berg if (local->ops->start_ap) 11481041638fSJohannes Berg ret = local->ops->start_ap(&local->hw, &sdata->vif); 11491041638fSJohannes Berg trace_drv_return_int(local, ret); 11501041638fSJohannes Berg return ret; 11511041638fSJohannes Berg } 11521041638fSJohannes Berg 11531041638fSJohannes Berg static inline void drv_stop_ap(struct ieee80211_local *local, 11541041638fSJohannes Berg struct ieee80211_sub_if_data *sdata) 11551041638fSJohannes Berg { 1156f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1157f6837ba8SJohannes Berg return; 11581041638fSJohannes Berg 11591041638fSJohannes Berg trace_drv_stop_ap(local, sdata); 11601041638fSJohannes Berg if (local->ops->stop_ap) 11611041638fSJohannes Berg local->ops->stop_ap(&local->hw, &sdata->vif); 11621041638fSJohannes Berg trace_drv_return_void(local); 11631041638fSJohannes Berg } 11641041638fSJohannes Berg 1165cf2c92d8SEliad Peller static inline void 1166cf2c92d8SEliad Peller drv_reconfig_complete(struct ieee80211_local *local, 1167cf2c92d8SEliad Peller enum ieee80211_reconfig_type reconfig_type) 11689214ad7fSJohannes Berg { 11699214ad7fSJohannes Berg might_sleep(); 11709214ad7fSJohannes Berg 1171cf2c92d8SEliad Peller trace_drv_reconfig_complete(local, reconfig_type); 1172cf2c92d8SEliad Peller if (local->ops->reconfig_complete) 1173cf2c92d8SEliad Peller local->ops->reconfig_complete(&local->hw, reconfig_type); 11749214ad7fSJohannes Berg trace_drv_return_void(local); 11759214ad7fSJohannes Berg } 11769214ad7fSJohannes Berg 1177de5fad81SYoni Divinsky static inline void 1178de5fad81SYoni Divinsky drv_set_default_unicast_key(struct ieee80211_local *local, 1179de5fad81SYoni Divinsky struct ieee80211_sub_if_data *sdata, 1180de5fad81SYoni Divinsky int key_idx) 1181de5fad81SYoni Divinsky { 1182f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1183f6837ba8SJohannes Berg return; 1184de5fad81SYoni Divinsky 1185de5fad81SYoni Divinsky WARN_ON_ONCE(key_idx < -1 || key_idx > 3); 1186de5fad81SYoni Divinsky 1187de5fad81SYoni Divinsky trace_drv_set_default_unicast_key(local, sdata, key_idx); 1188de5fad81SYoni Divinsky if (local->ops->set_default_unicast_key) 1189de5fad81SYoni Divinsky local->ops->set_default_unicast_key(&local->hw, &sdata->vif, 1190de5fad81SYoni Divinsky key_idx); 1191de5fad81SYoni Divinsky trace_drv_return_void(local); 1192de5fad81SYoni Divinsky } 1193de5fad81SYoni Divinsky 1194a65240c1SJohannes Berg #if IS_ENABLED(CONFIG_IPV6) 1195a65240c1SJohannes Berg static inline void drv_ipv6_addr_change(struct ieee80211_local *local, 1196a65240c1SJohannes Berg struct ieee80211_sub_if_data *sdata, 1197a65240c1SJohannes Berg struct inet6_dev *idev) 1198a65240c1SJohannes Berg { 1199a65240c1SJohannes Berg trace_drv_ipv6_addr_change(local, sdata); 1200a65240c1SJohannes Berg if (local->ops->ipv6_addr_change) 1201a65240c1SJohannes Berg local->ops->ipv6_addr_change(&local->hw, &sdata->vif, idev); 1202a65240c1SJohannes Berg trace_drv_return_void(local); 1203a65240c1SJohannes Berg } 1204a65240c1SJohannes Berg #endif 1205a65240c1SJohannes Berg 120673da7d5bSSimon Wunderlich static inline void 120773da7d5bSSimon Wunderlich drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata, 120873da7d5bSSimon Wunderlich struct cfg80211_chan_def *chandef) 120973da7d5bSSimon Wunderlich { 121073da7d5bSSimon Wunderlich struct ieee80211_local *local = sdata->local; 121173da7d5bSSimon Wunderlich 121273da7d5bSSimon Wunderlich if (local->ops->channel_switch_beacon) { 121373da7d5bSSimon Wunderlich trace_drv_channel_switch_beacon(local, sdata, chandef); 121473da7d5bSSimon Wunderlich local->ops->channel_switch_beacon(&local->hw, &sdata->vif, 121573da7d5bSSimon Wunderlich chandef); 121673da7d5bSSimon Wunderlich } 121773da7d5bSSimon Wunderlich } 121873da7d5bSSimon Wunderlich 12196d027bccSLuciano Coelho static inline int 12206d027bccSLuciano Coelho drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata, 12216d027bccSLuciano Coelho struct ieee80211_channel_switch *ch_switch) 12226d027bccSLuciano Coelho { 12236d027bccSLuciano Coelho struct ieee80211_local *local = sdata->local; 12246d027bccSLuciano Coelho int ret = 0; 12256d027bccSLuciano Coelho 12266d027bccSLuciano Coelho if (!check_sdata_in_driver(sdata)) 12276d027bccSLuciano Coelho return -EIO; 12286d027bccSLuciano Coelho 12296d027bccSLuciano Coelho trace_drv_pre_channel_switch(local, sdata, ch_switch); 12306d027bccSLuciano Coelho if (local->ops->pre_channel_switch) 12316d027bccSLuciano Coelho ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif, 12326d027bccSLuciano Coelho ch_switch); 12336d027bccSLuciano Coelho trace_drv_return_int(local, ret); 12346d027bccSLuciano Coelho return ret; 12356d027bccSLuciano Coelho } 12366d027bccSLuciano Coelho 1237f1d65583SLuciano Coelho static inline int 1238f1d65583SLuciano Coelho drv_post_channel_switch(struct ieee80211_sub_if_data *sdata) 1239f1d65583SLuciano Coelho { 1240f1d65583SLuciano Coelho struct ieee80211_local *local = sdata->local; 1241f1d65583SLuciano Coelho int ret = 0; 1242f1d65583SLuciano Coelho 1243f1d65583SLuciano Coelho if (!check_sdata_in_driver(sdata)) 1244f1d65583SLuciano Coelho return -EIO; 1245f1d65583SLuciano Coelho 1246f1d65583SLuciano Coelho trace_drv_post_channel_switch(local, sdata); 1247f1d65583SLuciano Coelho if (local->ops->post_channel_switch) 1248f1d65583SLuciano Coelho ret = local->ops->post_channel_switch(&local->hw, &sdata->vif); 1249f1d65583SLuciano Coelho trace_drv_return_int(local, ret); 1250f1d65583SLuciano Coelho return ret; 1251f1d65583SLuciano Coelho } 1252f1d65583SLuciano Coelho 125355fff501SJohannes Berg static inline int drv_join_ibss(struct ieee80211_local *local, 125455fff501SJohannes Berg struct ieee80211_sub_if_data *sdata) 125555fff501SJohannes Berg { 125655fff501SJohannes Berg int ret = 0; 125755fff501SJohannes Berg 125855fff501SJohannes Berg might_sleep(); 1259f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1260f6837ba8SJohannes Berg return -EIO; 126155fff501SJohannes Berg 126255fff501SJohannes Berg trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); 126355fff501SJohannes Berg if (local->ops->join_ibss) 126455fff501SJohannes Berg ret = local->ops->join_ibss(&local->hw, &sdata->vif); 126555fff501SJohannes Berg trace_drv_return_int(local, ret); 126655fff501SJohannes Berg return ret; 126755fff501SJohannes Berg } 126855fff501SJohannes Berg 126955fff501SJohannes Berg static inline void drv_leave_ibss(struct ieee80211_local *local, 127055fff501SJohannes Berg struct ieee80211_sub_if_data *sdata) 127155fff501SJohannes Berg { 127255fff501SJohannes Berg might_sleep(); 1273f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1274f6837ba8SJohannes Berg return; 127555fff501SJohannes Berg 127655fff501SJohannes Berg trace_drv_leave_ibss(local, sdata); 127755fff501SJohannes Berg if (local->ops->leave_ibss) 127855fff501SJohannes Berg local->ops->leave_ibss(&local->hw, &sdata->vif); 127955fff501SJohannes Berg trace_drv_return_void(local); 128055fff501SJohannes Berg } 128155fff501SJohannes Berg 1282cca674d4SAntonio Quartulli static inline u32 drv_get_expected_throughput(struct ieee80211_local *local, 1283cca674d4SAntonio Quartulli struct ieee80211_sta *sta) 1284cca674d4SAntonio Quartulli { 1285cca674d4SAntonio Quartulli u32 ret = 0; 1286cca674d4SAntonio Quartulli 1287cca674d4SAntonio Quartulli trace_drv_get_expected_throughput(sta); 1288cca674d4SAntonio Quartulli if (local->ops->get_expected_throughput) 1289cca674d4SAntonio Quartulli ret = local->ops->get_expected_throughput(sta); 1290cca674d4SAntonio Quartulli trace_drv_return_u32(local, ret); 1291cca674d4SAntonio Quartulli 1292cca674d4SAntonio Quartulli return ret; 1293cca674d4SAntonio Quartulli } 1294cca674d4SAntonio Quartulli 12955b3dc42bSFelix Fietkau static inline int drv_get_txpower(struct ieee80211_local *local, 12965b3dc42bSFelix Fietkau struct ieee80211_sub_if_data *sdata, int *dbm) 12975b3dc42bSFelix Fietkau { 12985b3dc42bSFelix Fietkau int ret; 12995b3dc42bSFelix Fietkau 13005b3dc42bSFelix Fietkau if (!local->ops->get_txpower) 13015b3dc42bSFelix Fietkau return -EOPNOTSUPP; 13025b3dc42bSFelix Fietkau 13035b3dc42bSFelix Fietkau ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm); 13045b3dc42bSFelix Fietkau trace_drv_get_txpower(local, sdata, *dbm, ret); 13055b3dc42bSFelix Fietkau 13065b3dc42bSFelix Fietkau return ret; 13075b3dc42bSFelix Fietkau } 13085b3dc42bSFelix Fietkau 1309a7a6bdd0SArik Nemtsov static inline int 1310a7a6bdd0SArik Nemtsov drv_tdls_channel_switch(struct ieee80211_local *local, 1311a7a6bdd0SArik Nemtsov struct ieee80211_sub_if_data *sdata, 1312a7a6bdd0SArik Nemtsov struct ieee80211_sta *sta, u8 oper_class, 1313a7a6bdd0SArik Nemtsov struct cfg80211_chan_def *chandef, 1314a7a6bdd0SArik Nemtsov struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie) 1315a7a6bdd0SArik Nemtsov { 1316a7a6bdd0SArik Nemtsov int ret; 1317a7a6bdd0SArik Nemtsov 1318a7a6bdd0SArik Nemtsov might_sleep(); 1319a7a6bdd0SArik Nemtsov if (!check_sdata_in_driver(sdata)) 1320a7a6bdd0SArik Nemtsov return -EIO; 1321a7a6bdd0SArik Nemtsov 1322a7a6bdd0SArik Nemtsov if (!local->ops->tdls_channel_switch) 1323a7a6bdd0SArik Nemtsov return -EOPNOTSUPP; 1324a7a6bdd0SArik Nemtsov 1325a7a6bdd0SArik Nemtsov trace_drv_tdls_channel_switch(local, sdata, sta, oper_class, chandef); 1326a7a6bdd0SArik Nemtsov ret = local->ops->tdls_channel_switch(&local->hw, &sdata->vif, sta, 1327a7a6bdd0SArik Nemtsov oper_class, chandef, tmpl_skb, 1328a7a6bdd0SArik Nemtsov ch_sw_tm_ie); 1329a7a6bdd0SArik Nemtsov trace_drv_return_int(local, ret); 1330a7a6bdd0SArik Nemtsov return ret; 1331a7a6bdd0SArik Nemtsov } 1332a7a6bdd0SArik Nemtsov 1333a7a6bdd0SArik Nemtsov static inline void 1334a7a6bdd0SArik Nemtsov drv_tdls_cancel_channel_switch(struct ieee80211_local *local, 1335a7a6bdd0SArik Nemtsov struct ieee80211_sub_if_data *sdata, 1336a7a6bdd0SArik Nemtsov struct ieee80211_sta *sta) 1337a7a6bdd0SArik Nemtsov { 1338a7a6bdd0SArik Nemtsov might_sleep(); 1339a7a6bdd0SArik Nemtsov if (!check_sdata_in_driver(sdata)) 1340a7a6bdd0SArik Nemtsov return; 1341a7a6bdd0SArik Nemtsov 1342a7a6bdd0SArik Nemtsov if (!local->ops->tdls_cancel_channel_switch) 1343a7a6bdd0SArik Nemtsov return; 1344a7a6bdd0SArik Nemtsov 1345a7a6bdd0SArik Nemtsov trace_drv_tdls_cancel_channel_switch(local, sdata, sta); 1346a7a6bdd0SArik Nemtsov local->ops->tdls_cancel_channel_switch(&local->hw, &sdata->vif, sta); 1347a7a6bdd0SArik Nemtsov trace_drv_return_void(local); 1348a7a6bdd0SArik Nemtsov } 1349a7a6bdd0SArik Nemtsov 13508a4d32f3SArik Nemtsov static inline void 13518a4d32f3SArik Nemtsov drv_tdls_recv_channel_switch(struct ieee80211_local *local, 13528a4d32f3SArik Nemtsov struct ieee80211_sub_if_data *sdata, 13538a4d32f3SArik Nemtsov struct ieee80211_tdls_ch_sw_params *params) 13548a4d32f3SArik Nemtsov { 13558a4d32f3SArik Nemtsov trace_drv_tdls_recv_channel_switch(local, sdata, params); 13568a4d32f3SArik Nemtsov if (local->ops->tdls_recv_channel_switch) 13578a4d32f3SArik Nemtsov local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif, 13588a4d32f3SArik Nemtsov params); 13598a4d32f3SArik Nemtsov trace_drv_return_void(local); 13608a4d32f3SArik Nemtsov } 13618a4d32f3SArik Nemtsov 1362ba8c3d6fSFelix Fietkau static inline void drv_wake_tx_queue(struct ieee80211_local *local, 1363ba8c3d6fSFelix Fietkau struct txq_info *txq) 1364ba8c3d6fSFelix Fietkau { 1365ba8c3d6fSFelix Fietkau struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); 1366ba8c3d6fSFelix Fietkau 1367ba8c3d6fSFelix Fietkau if (!check_sdata_in_driver(sdata)) 1368ba8c3d6fSFelix Fietkau return; 1369ba8c3d6fSFelix Fietkau 1370ba8c3d6fSFelix Fietkau trace_drv_wake_tx_queue(local, sdata, txq); 1371ba8c3d6fSFelix Fietkau local->ops->wake_tx_queue(&local->hw, &txq->txq); 1372ba8c3d6fSFelix Fietkau } 1373ba8c3d6fSFelix Fietkau 137424487981SJohannes Berg #endif /* __MAC80211_DRIVER_OPS */ 1375