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 && 14931eba5bcSFelix Fietkau !(local->hw.flags & IEEE80211_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 && 2175bbe754dSJohannes Berg sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) 2185bbe754dSJohannes Berg return; 2195bbe754dSJohannes Berg 2205bbe754dSJohannes Berg if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || 2215bbe754dSJohannes Berg sdata->vif.type == NL80211_IFTYPE_MONITOR)) 2225bbe754dSJohannes Berg return; 223b8dc1a35SJohannes Berg 224f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 225f6837ba8SJohannes Berg return; 2267b7eab6fSJohannes Berg 2274efc76bdSJohannes Berg trace_drv_bss_info_changed(local, sdata, info, changed); 22824487981SJohannes Berg if (local->ops->bss_info_changed) 22912375ef9SJohannes Berg local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); 2304efc76bdSJohannes Berg trace_drv_return_void(local); 23124487981SJohannes Berg } 23224487981SJohannes Berg 2333ac64beeSJohannes Berg static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 23422bedad3SJiri Pirko struct netdev_hw_addr_list *mc_list) 23524487981SJohannes Berg { 2363ac64beeSJohannes Berg u64 ret = 0; 2373ac64beeSJohannes Berg 2384efc76bdSJohannes Berg trace_drv_prepare_multicast(local, mc_list->count); 2394efc76bdSJohannes Berg 2403ac64beeSJohannes Berg if (local->ops->prepare_multicast) 24122bedad3SJiri Pirko ret = local->ops->prepare_multicast(&local->hw, mc_list); 2423ac64beeSJohannes Berg 2434efc76bdSJohannes Berg trace_drv_return_u64(local, ret); 2443ac64beeSJohannes Berg 2453ac64beeSJohannes Berg return ret; 2463ac64beeSJohannes Berg } 2473ac64beeSJohannes Berg 2483ac64beeSJohannes Berg static inline void drv_configure_filter(struct ieee80211_local *local, 2493ac64beeSJohannes Berg unsigned int changed_flags, 2503ac64beeSJohannes Berg unsigned int *total_flags, 2513ac64beeSJohannes Berg u64 multicast) 2523ac64beeSJohannes Berg { 2533ac64beeSJohannes Berg might_sleep(); 2543ac64beeSJohannes Berg 2550a2b8bb2SJohannes Berg trace_drv_configure_filter(local, changed_flags, total_flags, 2563ac64beeSJohannes Berg multicast); 2574efc76bdSJohannes Berg local->ops->configure_filter(&local->hw, changed_flags, total_flags, 2584efc76bdSJohannes Berg multicast); 2594efc76bdSJohannes Berg trace_drv_return_void(local); 26024487981SJohannes Berg } 26124487981SJohannes Berg 26224487981SJohannes Berg static inline int drv_set_tim(struct ieee80211_local *local, 26324487981SJohannes Berg struct ieee80211_sta *sta, bool set) 26424487981SJohannes Berg { 2650a2b8bb2SJohannes Berg int ret = 0; 2664efc76bdSJohannes Berg trace_drv_set_tim(local, sta, set); 26724487981SJohannes Berg if (local->ops->set_tim) 2680a2b8bb2SJohannes Berg ret = local->ops->set_tim(&local->hw, sta, set); 2694efc76bdSJohannes Berg trace_drv_return_int(local, ret); 2700a2b8bb2SJohannes Berg return ret; 27124487981SJohannes Berg } 27224487981SJohannes Berg 27324487981SJohannes Berg static inline int drv_set_key(struct ieee80211_local *local, 27412375ef9SJohannes Berg enum set_key_cmd cmd, 27512375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 27624487981SJohannes Berg struct ieee80211_sta *sta, 27724487981SJohannes Berg struct ieee80211_key_conf *key) 27824487981SJohannes Berg { 279e1781ed3SKalle Valo int ret; 280e1781ed3SKalle Valo 281e1781ed3SKalle Valo might_sleep(); 282e1781ed3SKalle Valo 283077f4939SJohannes Berg sdata = get_bss_sdata(sdata); 284f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 285f6837ba8SJohannes Berg return -EIO; 2867b7eab6fSJohannes Berg 2874efc76bdSJohannes Berg trace_drv_set_key(local, cmd, sdata, sta, key); 288e1781ed3SKalle Valo ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); 2894efc76bdSJohannes Berg trace_drv_return_int(local, ret); 2900a2b8bb2SJohannes Berg return ret; 29124487981SJohannes Berg } 29224487981SJohannes Berg 29324487981SJohannes Berg static inline void drv_update_tkip_key(struct ieee80211_local *local, 294b3fbdcf4SJohannes Berg struct ieee80211_sub_if_data *sdata, 29524487981SJohannes Berg struct ieee80211_key_conf *conf, 296b3fbdcf4SJohannes Berg struct sta_info *sta, u32 iv32, 29724487981SJohannes Berg u16 *phase1key) 29824487981SJohannes Berg { 299b3fbdcf4SJohannes Berg struct ieee80211_sta *ista = NULL; 300b3fbdcf4SJohannes Berg 301b3fbdcf4SJohannes Berg if (sta) 302b3fbdcf4SJohannes Berg ista = &sta->sta; 303b3fbdcf4SJohannes Berg 304077f4939SJohannes Berg sdata = get_bss_sdata(sdata); 305f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 306f6837ba8SJohannes Berg return; 3077b7eab6fSJohannes Berg 3084efc76bdSJohannes Berg trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); 30924487981SJohannes Berg if (local->ops->update_tkip_key) 310b3fbdcf4SJohannes Berg local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, 311b3fbdcf4SJohannes Berg ista, iv32, phase1key); 3124efc76bdSJohannes Berg trace_drv_return_void(local); 31324487981SJohannes Berg } 31424487981SJohannes Berg 31524487981SJohannes Berg static inline int drv_hw_scan(struct ieee80211_local *local, 316a060bbfeSJohannes Berg struct ieee80211_sub_if_data *sdata, 317c56ef672SDavid Spinadel struct ieee80211_scan_request *req) 31824487981SJohannes Berg { 319e1781ed3SKalle Valo int ret; 320e1781ed3SKalle Valo 321e1781ed3SKalle Valo might_sleep(); 322e1781ed3SKalle Valo 323f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 324f6837ba8SJohannes Berg return -EIO; 3257b7eab6fSJohannes Berg 32679f460caSLuciano Coelho trace_drv_hw_scan(local, sdata); 327a060bbfeSJohannes Berg ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); 3284efc76bdSJohannes Berg trace_drv_return_int(local, ret); 3290a2b8bb2SJohannes Berg return ret; 33024487981SJohannes Berg } 33124487981SJohannes Berg 332b856439bSEliad Peller static inline void drv_cancel_hw_scan(struct ieee80211_local *local, 333b856439bSEliad Peller struct ieee80211_sub_if_data *sdata) 334b856439bSEliad Peller { 335b856439bSEliad Peller might_sleep(); 336b856439bSEliad Peller 337f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 338f6837ba8SJohannes Berg return; 3397b7eab6fSJohannes Berg 340b856439bSEliad Peller trace_drv_cancel_hw_scan(local, sdata); 341b856439bSEliad Peller local->ops->cancel_hw_scan(&local->hw, &sdata->vif); 342b856439bSEliad Peller trace_drv_return_void(local); 343b856439bSEliad Peller } 344b856439bSEliad Peller 34579f460caSLuciano Coelho static inline int 34679f460caSLuciano Coelho drv_sched_scan_start(struct ieee80211_local *local, 34779f460caSLuciano Coelho struct ieee80211_sub_if_data *sdata, 34879f460caSLuciano Coelho struct cfg80211_sched_scan_request *req, 349633e2713SDavid Spinadel struct ieee80211_scan_ies *ies) 35079f460caSLuciano Coelho { 35179f460caSLuciano Coelho int ret; 35279f460caSLuciano Coelho 35379f460caSLuciano Coelho might_sleep(); 35479f460caSLuciano Coelho 355f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 356f6837ba8SJohannes Berg return -EIO; 3577b7eab6fSJohannes Berg 35879f460caSLuciano Coelho trace_drv_sched_scan_start(local, sdata); 35979f460caSLuciano Coelho ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, 36079f460caSLuciano Coelho req, ies); 36179f460caSLuciano Coelho trace_drv_return_int(local, ret); 36279f460caSLuciano Coelho return ret; 36379f460caSLuciano Coelho } 36479f460caSLuciano Coelho 36537e3308cSJohannes Berg static inline int drv_sched_scan_stop(struct ieee80211_local *local, 36679f460caSLuciano Coelho struct ieee80211_sub_if_data *sdata) 36779f460caSLuciano Coelho { 36837e3308cSJohannes Berg int ret; 36937e3308cSJohannes Berg 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_stop(local, sdata); 37637e3308cSJohannes Berg ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); 37737e3308cSJohannes Berg trace_drv_return_int(local, ret); 37837e3308cSJohannes Berg 37937e3308cSJohannes Berg return ret; 38079f460caSLuciano Coelho } 38179f460caSLuciano Coelho 38224487981SJohannes Berg static inline void drv_sw_scan_start(struct ieee80211_local *local) 38324487981SJohannes Berg { 384e1781ed3SKalle Valo might_sleep(); 385e1781ed3SKalle Valo 3864efc76bdSJohannes Berg trace_drv_sw_scan_start(local); 38724487981SJohannes Berg if (local->ops->sw_scan_start) 38824487981SJohannes Berg local->ops->sw_scan_start(&local->hw); 3894efc76bdSJohannes Berg trace_drv_return_void(local); 39024487981SJohannes Berg } 39124487981SJohannes Berg 39224487981SJohannes Berg static inline void drv_sw_scan_complete(struct ieee80211_local *local) 39324487981SJohannes Berg { 394e1781ed3SKalle Valo might_sleep(); 395e1781ed3SKalle Valo 3964efc76bdSJohannes Berg trace_drv_sw_scan_complete(local); 39724487981SJohannes Berg if (local->ops->sw_scan_complete) 39824487981SJohannes Berg local->ops->sw_scan_complete(&local->hw); 3994efc76bdSJohannes Berg trace_drv_return_void(local); 40024487981SJohannes Berg } 40124487981SJohannes Berg 40224487981SJohannes Berg static inline int drv_get_stats(struct ieee80211_local *local, 40324487981SJohannes Berg struct ieee80211_low_level_stats *stats) 40424487981SJohannes Berg { 4050a2b8bb2SJohannes Berg int ret = -EOPNOTSUPP; 4060a2b8bb2SJohannes Berg 407e1781ed3SKalle Valo might_sleep(); 408e1781ed3SKalle Valo 4090a2b8bb2SJohannes Berg if (local->ops->get_stats) 4100a2b8bb2SJohannes Berg ret = local->ops->get_stats(&local->hw, stats); 4110a2b8bb2SJohannes Berg trace_drv_get_stats(local, stats, ret); 4120a2b8bb2SJohannes Berg 4130a2b8bb2SJohannes Berg return ret; 41424487981SJohannes Berg } 41524487981SJohannes Berg 41624487981SJohannes Berg static inline void drv_get_tkip_seq(struct ieee80211_local *local, 41724487981SJohannes Berg u8 hw_key_idx, u32 *iv32, u16 *iv16) 41824487981SJohannes Berg { 41924487981SJohannes Berg if (local->ops->get_tkip_seq) 42024487981SJohannes Berg local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); 4210a2b8bb2SJohannes Berg trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); 42224487981SJohannes Berg } 42324487981SJohannes Berg 424f23a4780SArik Nemtsov static inline int drv_set_frag_threshold(struct ieee80211_local *local, 425f23a4780SArik Nemtsov u32 value) 426f23a4780SArik Nemtsov { 427f23a4780SArik Nemtsov int ret = 0; 428f23a4780SArik Nemtsov 429f23a4780SArik Nemtsov might_sleep(); 430f23a4780SArik Nemtsov 431f23a4780SArik Nemtsov trace_drv_set_frag_threshold(local, value); 432f23a4780SArik Nemtsov if (local->ops->set_frag_threshold) 433f23a4780SArik Nemtsov ret = local->ops->set_frag_threshold(&local->hw, value); 434f23a4780SArik Nemtsov trace_drv_return_int(local, ret); 435f23a4780SArik Nemtsov return ret; 436f23a4780SArik Nemtsov } 437f23a4780SArik Nemtsov 43824487981SJohannes Berg static inline int drv_set_rts_threshold(struct ieee80211_local *local, 43924487981SJohannes Berg u32 value) 44024487981SJohannes Berg { 4410a2b8bb2SJohannes Berg int ret = 0; 442e1781ed3SKalle Valo 443e1781ed3SKalle Valo might_sleep(); 444e1781ed3SKalle Valo 4454efc76bdSJohannes Berg trace_drv_set_rts_threshold(local, value); 44624487981SJohannes Berg if (local->ops->set_rts_threshold) 4470a2b8bb2SJohannes Berg ret = local->ops->set_rts_threshold(&local->hw, value); 4484efc76bdSJohannes Berg trace_drv_return_int(local, ret); 4490a2b8bb2SJohannes Berg return ret; 45024487981SJohannes Berg } 45124487981SJohannes Berg 452310bc676SLukáš Turek static inline int drv_set_coverage_class(struct ieee80211_local *local, 453a4bcaf55SLorenzo Bianconi s16 value) 454310bc676SLukáš Turek { 455310bc676SLukáš Turek int ret = 0; 456310bc676SLukáš Turek might_sleep(); 457310bc676SLukáš Turek 4584efc76bdSJohannes Berg trace_drv_set_coverage_class(local, value); 459310bc676SLukáš Turek if (local->ops->set_coverage_class) 460310bc676SLukáš Turek local->ops->set_coverage_class(&local->hw, value); 461310bc676SLukáš Turek else 462310bc676SLukáš Turek ret = -EOPNOTSUPP; 463310bc676SLukáš Turek 4644efc76bdSJohannes Berg trace_drv_return_int(local, ret); 465310bc676SLukáš Turek return ret; 466310bc676SLukáš Turek } 467310bc676SLukáš Turek 46824487981SJohannes Berg static inline void drv_sta_notify(struct ieee80211_local *local, 46912375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 47024487981SJohannes Berg enum sta_notify_cmd cmd, 47124487981SJohannes Berg struct ieee80211_sta *sta) 47224487981SJohannes Berg { 473bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 474f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 475f6837ba8SJohannes Berg return; 4767b7eab6fSJohannes Berg 4774efc76bdSJohannes Berg trace_drv_sta_notify(local, sdata, cmd, sta); 47824487981SJohannes Berg if (local->ops->sta_notify) 47912375ef9SJohannes Berg local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); 4804efc76bdSJohannes Berg trace_drv_return_void(local); 48124487981SJohannes Berg } 48224487981SJohannes Berg 48334e89507SJohannes Berg static inline int drv_sta_add(struct ieee80211_local *local, 48434e89507SJohannes Berg struct ieee80211_sub_if_data *sdata, 48534e89507SJohannes Berg struct ieee80211_sta *sta) 48634e89507SJohannes Berg { 48734e89507SJohannes Berg int ret = 0; 48834e89507SJohannes Berg 48934e89507SJohannes Berg might_sleep(); 49034e89507SJohannes Berg 491bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 492f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 493f6837ba8SJohannes Berg return -EIO; 4947b7eab6fSJohannes Berg 4954efc76bdSJohannes Berg trace_drv_sta_add(local, sdata, sta); 49634e89507SJohannes Berg if (local->ops->sta_add) 49734e89507SJohannes Berg ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); 49834e89507SJohannes Berg 4994efc76bdSJohannes Berg trace_drv_return_int(local, ret); 50034e89507SJohannes Berg 50134e89507SJohannes Berg return ret; 50234e89507SJohannes Berg } 50334e89507SJohannes Berg 50434e89507SJohannes Berg static inline void drv_sta_remove(struct ieee80211_local *local, 50534e89507SJohannes Berg struct ieee80211_sub_if_data *sdata, 50634e89507SJohannes Berg struct ieee80211_sta *sta) 50734e89507SJohannes Berg { 50834e89507SJohannes Berg might_sleep(); 50934e89507SJohannes Berg 510bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 511f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 512f6837ba8SJohannes Berg return; 5137b7eab6fSJohannes Berg 5144efc76bdSJohannes Berg trace_drv_sta_remove(local, sdata, sta); 51534e89507SJohannes Berg if (local->ops->sta_remove) 51634e89507SJohannes Berg local->ops->sta_remove(&local->hw, &sdata->vif, sta); 51734e89507SJohannes Berg 5184efc76bdSJohannes Berg trace_drv_return_void(local); 51934e89507SJohannes Berg } 52034e89507SJohannes Berg 52177d2ece6SSujith Manoharan #ifdef CONFIG_MAC80211_DEBUGFS 52277d2ece6SSujith Manoharan static inline void drv_sta_add_debugfs(struct ieee80211_local *local, 52377d2ece6SSujith Manoharan struct ieee80211_sub_if_data *sdata, 52477d2ece6SSujith Manoharan struct ieee80211_sta *sta, 52577d2ece6SSujith Manoharan struct dentry *dir) 52677d2ece6SSujith Manoharan { 52777d2ece6SSujith Manoharan might_sleep(); 52877d2ece6SSujith Manoharan 52977d2ece6SSujith Manoharan sdata = get_bss_sdata(sdata); 530f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 531f6837ba8SJohannes Berg return; 53277d2ece6SSujith Manoharan 53377d2ece6SSujith Manoharan if (local->ops->sta_add_debugfs) 53477d2ece6SSujith Manoharan local->ops->sta_add_debugfs(&local->hw, &sdata->vif, 53577d2ece6SSujith Manoharan sta, dir); 53677d2ece6SSujith Manoharan } 53777d2ece6SSujith Manoharan 53877d2ece6SSujith Manoharan static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, 53977d2ece6SSujith Manoharan struct ieee80211_sub_if_data *sdata, 54077d2ece6SSujith Manoharan struct ieee80211_sta *sta, 54177d2ece6SSujith Manoharan struct dentry *dir) 54277d2ece6SSujith Manoharan { 54377d2ece6SSujith Manoharan might_sleep(); 54477d2ece6SSujith Manoharan 54577d2ece6SSujith Manoharan sdata = get_bss_sdata(sdata); 54677d2ece6SSujith Manoharan check_sdata_in_driver(sdata); 54777d2ece6SSujith Manoharan 54877d2ece6SSujith Manoharan if (local->ops->sta_remove_debugfs) 54977d2ece6SSujith Manoharan local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, 55077d2ece6SSujith Manoharan sta, dir); 55177d2ece6SSujith Manoharan } 55277d2ece6SSujith Manoharan #endif 55377d2ece6SSujith Manoharan 5546a9d1b91SJohannes Berg static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, 5556a9d1b91SJohannes Berg struct ieee80211_sub_if_data *sdata, 5566a9d1b91SJohannes Berg struct sta_info *sta) 5576a9d1b91SJohannes Berg { 5586a9d1b91SJohannes Berg might_sleep(); 5596a9d1b91SJohannes Berg 5606a9d1b91SJohannes Berg sdata = get_bss_sdata(sdata); 561f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 562f6837ba8SJohannes Berg return; 5636a9d1b91SJohannes Berg 5646a9d1b91SJohannes Berg trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); 5656a9d1b91SJohannes Berg if (local->ops->sta_pre_rcu_remove) 5666a9d1b91SJohannes Berg local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif, 5676a9d1b91SJohannes Berg &sta->sta); 5686a9d1b91SJohannes Berg trace_drv_return_void(local); 5696a9d1b91SJohannes Berg } 5706a9d1b91SJohannes Berg 571f09603a2SJohannes Berg static inline __must_check 572f09603a2SJohannes Berg int drv_sta_state(struct ieee80211_local *local, 573f09603a2SJohannes Berg struct ieee80211_sub_if_data *sdata, 574f09603a2SJohannes Berg struct sta_info *sta, 575f09603a2SJohannes Berg enum ieee80211_sta_state old_state, 576f09603a2SJohannes Berg enum ieee80211_sta_state new_state) 577f09603a2SJohannes Berg { 578f09603a2SJohannes Berg int ret = 0; 579f09603a2SJohannes Berg 580f09603a2SJohannes Berg might_sleep(); 581f09603a2SJohannes Berg 582f09603a2SJohannes Berg sdata = get_bss_sdata(sdata); 583f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 584f6837ba8SJohannes Berg return -EIO; 585f09603a2SJohannes Berg 586f09603a2SJohannes Berg trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); 587a4ec45a4SJohannes Berg if (local->ops->sta_state) { 588f09603a2SJohannes Berg ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, 589f09603a2SJohannes Berg old_state, new_state); 590a4ec45a4SJohannes Berg } else if (old_state == IEEE80211_STA_AUTH && 591a4ec45a4SJohannes Berg new_state == IEEE80211_STA_ASSOC) { 592a4ec45a4SJohannes Berg ret = drv_sta_add(local, sdata, &sta->sta); 593a4ec45a4SJohannes Berg if (ret == 0) 594a4ec45a4SJohannes Berg sta->uploaded = true; 595a4ec45a4SJohannes Berg } else if (old_state == IEEE80211_STA_ASSOC && 596a4ec45a4SJohannes Berg new_state == IEEE80211_STA_AUTH) { 597a4ec45a4SJohannes Berg drv_sta_remove(local, sdata, &sta->sta); 598a4ec45a4SJohannes Berg } 599f09603a2SJohannes Berg trace_drv_return_int(local, ret); 600f09603a2SJohannes Berg return ret; 601f09603a2SJohannes Berg } 602f09603a2SJohannes Berg 6038f727ef3SJohannes Berg static inline void drv_sta_rc_update(struct ieee80211_local *local, 6048f727ef3SJohannes Berg struct ieee80211_sub_if_data *sdata, 6058f727ef3SJohannes Berg struct ieee80211_sta *sta, u32 changed) 6068f727ef3SJohannes Berg { 6078f727ef3SJohannes Berg sdata = get_bss_sdata(sdata); 608f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 609f6837ba8SJohannes Berg return; 6108f727ef3SJohannes Berg 611e687f61eSAntonio Quartulli WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && 612f68d776aSThomas Pedersen (sdata->vif.type != NL80211_IFTYPE_ADHOC && 613f68d776aSThomas Pedersen sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); 614e687f61eSAntonio Quartulli 6158f727ef3SJohannes Berg trace_drv_sta_rc_update(local, sdata, sta, changed); 6168f727ef3SJohannes Berg if (local->ops->sta_rc_update) 6178f727ef3SJohannes Berg local->ops->sta_rc_update(&local->hw, &sdata->vif, 6188f727ef3SJohannes Berg sta, changed); 6198f727ef3SJohannes Berg 6208f727ef3SJohannes Berg trace_drv_return_void(local); 6218f727ef3SJohannes Berg } 6228f727ef3SJohannes Berg 623f6f3def3SEliad Peller static inline int drv_conf_tx(struct ieee80211_local *local, 624a3304b0aSJohannes Berg struct ieee80211_sub_if_data *sdata, u16 ac, 62524487981SJohannes Berg const struct ieee80211_tx_queue_params *params) 62624487981SJohannes Berg { 6270a2b8bb2SJohannes Berg int ret = -EOPNOTSUPP; 628e1781ed3SKalle Valo 629e1781ed3SKalle Valo might_sleep(); 630e1781ed3SKalle Valo 631f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 632f6837ba8SJohannes Berg return -EIO; 6337b7eab6fSJohannes Berg 634a3304b0aSJohannes Berg trace_drv_conf_tx(local, sdata, ac, params); 63524487981SJohannes Berg if (local->ops->conf_tx) 6368a3a3c85SEliad Peller ret = local->ops->conf_tx(&local->hw, &sdata->vif, 637a3304b0aSJohannes Berg ac, params); 6384efc76bdSJohannes Berg trace_drv_return_int(local, ret); 6390a2b8bb2SJohannes Berg return ret; 64024487981SJohannes Berg } 64124487981SJohannes Berg 64237a41b4aSEliad Peller static inline u64 drv_get_tsf(struct ieee80211_local *local, 64337a41b4aSEliad Peller struct ieee80211_sub_if_data *sdata) 64424487981SJohannes Berg { 6450a2b8bb2SJohannes Berg u64 ret = -1ULL; 646e1781ed3SKalle Valo 647e1781ed3SKalle Valo might_sleep(); 648e1781ed3SKalle Valo 649f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 650f6837ba8SJohannes Berg return ret; 6517b7eab6fSJohannes Berg 65237a41b4aSEliad Peller trace_drv_get_tsf(local, sdata); 65324487981SJohannes Berg if (local->ops->get_tsf) 65437a41b4aSEliad Peller ret = local->ops->get_tsf(&local->hw, &sdata->vif); 6554efc76bdSJohannes Berg trace_drv_return_u64(local, ret); 6560a2b8bb2SJohannes Berg return ret; 65724487981SJohannes Berg } 65824487981SJohannes Berg 65937a41b4aSEliad Peller static inline void drv_set_tsf(struct ieee80211_local *local, 66037a41b4aSEliad Peller struct ieee80211_sub_if_data *sdata, 66137a41b4aSEliad Peller u64 tsf) 66224487981SJohannes Berg { 663e1781ed3SKalle Valo might_sleep(); 664e1781ed3SKalle Valo 665f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 666f6837ba8SJohannes Berg return; 6677b7eab6fSJohannes Berg 66837a41b4aSEliad Peller trace_drv_set_tsf(local, sdata, tsf); 66924487981SJohannes Berg if (local->ops->set_tsf) 67037a41b4aSEliad Peller local->ops->set_tsf(&local->hw, &sdata->vif, tsf); 6714efc76bdSJohannes Berg trace_drv_return_void(local); 67224487981SJohannes Berg } 67324487981SJohannes Berg 67437a41b4aSEliad Peller static inline void drv_reset_tsf(struct ieee80211_local *local, 67537a41b4aSEliad Peller struct ieee80211_sub_if_data *sdata) 67624487981SJohannes Berg { 677e1781ed3SKalle Valo might_sleep(); 678e1781ed3SKalle Valo 679f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 680f6837ba8SJohannes Berg return; 6817b7eab6fSJohannes Berg 68237a41b4aSEliad Peller trace_drv_reset_tsf(local, sdata); 68324487981SJohannes Berg if (local->ops->reset_tsf) 68437a41b4aSEliad Peller local->ops->reset_tsf(&local->hw, &sdata->vif); 6854efc76bdSJohannes Berg trace_drv_return_void(local); 68624487981SJohannes Berg } 68724487981SJohannes Berg 68824487981SJohannes Berg static inline int drv_tx_last_beacon(struct ieee80211_local *local) 68924487981SJohannes Berg { 69002582e9bSMasanari Iida int ret = 0; /* default unsupported op for less congestion */ 691e1781ed3SKalle Valo 692e1781ed3SKalle Valo might_sleep(); 693e1781ed3SKalle Valo 6944efc76bdSJohannes Berg trace_drv_tx_last_beacon(local); 69524487981SJohannes Berg if (local->ops->tx_last_beacon) 6960a2b8bb2SJohannes Berg ret = local->ops->tx_last_beacon(&local->hw); 6974efc76bdSJohannes Berg trace_drv_return_int(local, ret); 6980a2b8bb2SJohannes Berg return ret; 69924487981SJohannes Berg } 70024487981SJohannes Berg 70124487981SJohannes Berg static inline int drv_ampdu_action(struct ieee80211_local *local, 70212375ef9SJohannes Berg struct ieee80211_sub_if_data *sdata, 70324487981SJohannes Berg enum ieee80211_ampdu_mlme_action action, 70424487981SJohannes Berg struct ieee80211_sta *sta, u16 tid, 7050b01f030SJohannes Berg u16 *ssn, u8 buf_size) 70624487981SJohannes Berg { 7070a2b8bb2SJohannes Berg int ret = -EOPNOTSUPP; 708cfcdbde3SJohannes Berg 709cfcdbde3SJohannes Berg might_sleep(); 710cfcdbde3SJohannes Berg 711bc192f89SFelix Fietkau sdata = get_bss_sdata(sdata); 712f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 713f6837ba8SJohannes Berg return -EIO; 7147b7eab6fSJohannes Berg 7150b01f030SJohannes Berg trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); 7164efc76bdSJohannes Berg 71724487981SJohannes Berg if (local->ops->ampdu_action) 71812375ef9SJohannes Berg ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, 7190b01f030SJohannes Berg sta, tid, ssn, buf_size); 72085ad181eSJohannes Berg 7214efc76bdSJohannes Berg trace_drv_return_int(local, ret); 7224efc76bdSJohannes Berg 7230a2b8bb2SJohannes Berg return ret; 72424487981SJohannes Berg } 7251f87f7d3SJohannes Berg 7261289723eSHolger Schurig static inline int drv_get_survey(struct ieee80211_local *local, int idx, 7271289723eSHolger Schurig struct survey_info *survey) 7281289723eSHolger Schurig { 7291289723eSHolger Schurig int ret = -EOPNOTSUPP; 730c466d4efSJohn W. Linville 731c466d4efSJohn W. Linville trace_drv_get_survey(local, idx, survey); 732c466d4efSJohn W. Linville 73335dd0509SHolger Schurig if (local->ops->get_survey) 7341289723eSHolger Schurig ret = local->ops->get_survey(&local->hw, idx, survey); 735c466d4efSJohn W. Linville 736c466d4efSJohn W. Linville trace_drv_return_int(local, ret); 737c466d4efSJohn W. Linville 7381289723eSHolger Schurig return ret; 7391289723eSHolger Schurig } 7401f87f7d3SJohannes Berg 7411f87f7d3SJohannes Berg static inline void drv_rfkill_poll(struct ieee80211_local *local) 7421f87f7d3SJohannes Berg { 743e1781ed3SKalle Valo might_sleep(); 744e1781ed3SKalle Valo 7451f87f7d3SJohannes Berg if (local->ops->rfkill_poll) 7461f87f7d3SJohannes Berg local->ops->rfkill_poll(&local->hw); 7471f87f7d3SJohannes Berg } 748a80f7c0bSJohannes Berg 74939ecc01dSJohannes Berg static inline void drv_flush(struct ieee80211_local *local, 75077be2c54SEmmanuel Grumbach struct ieee80211_sub_if_data *sdata, 75139ecc01dSJohannes Berg u32 queues, bool drop) 752a80f7c0bSJohannes Berg { 75377be2c54SEmmanuel Grumbach struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; 75477be2c54SEmmanuel Grumbach 755e1781ed3SKalle Valo might_sleep(); 756e1781ed3SKalle Valo 757f6837ba8SJohannes Berg if (sdata && !check_sdata_in_driver(sdata)) 758f6837ba8SJohannes Berg return; 75977be2c54SEmmanuel Grumbach 76039ecc01dSJohannes Berg trace_drv_flush(local, queues, drop); 761a80f7c0bSJohannes Berg if (local->ops->flush) 76277be2c54SEmmanuel Grumbach local->ops->flush(&local->hw, vif, queues, drop); 7634efc76bdSJohannes Berg trace_drv_return_void(local); 764a80f7c0bSJohannes Berg } 7655ce6e438SJohannes Berg 7665ce6e438SJohannes Berg static inline void drv_channel_switch(struct ieee80211_local *local, 7675ce6e438SJohannes Berg struct ieee80211_channel_switch *ch_switch) 7685ce6e438SJohannes Berg { 7695ce6e438SJohannes Berg might_sleep(); 7705ce6e438SJohannes Berg 7715ce6e438SJohannes Berg trace_drv_channel_switch(local, ch_switch); 7724efc76bdSJohannes Berg local->ops->channel_switch(&local->hw, ch_switch); 7734efc76bdSJohannes Berg trace_drv_return_void(local); 7745ce6e438SJohannes Berg } 7755ce6e438SJohannes Berg 77615d96753SBruno Randolf 77715d96753SBruno Randolf static inline int drv_set_antenna(struct ieee80211_local *local, 77815d96753SBruno Randolf u32 tx_ant, u32 rx_ant) 77915d96753SBruno Randolf { 78015d96753SBruno Randolf int ret = -EOPNOTSUPP; 78115d96753SBruno Randolf might_sleep(); 78215d96753SBruno Randolf if (local->ops->set_antenna) 78315d96753SBruno Randolf ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant); 78415d96753SBruno Randolf trace_drv_set_antenna(local, tx_ant, rx_ant, ret); 78515d96753SBruno Randolf return ret; 78615d96753SBruno Randolf } 78715d96753SBruno Randolf 78815d96753SBruno Randolf static inline int drv_get_antenna(struct ieee80211_local *local, 78915d96753SBruno Randolf u32 *tx_ant, u32 *rx_ant) 79015d96753SBruno Randolf { 79115d96753SBruno Randolf int ret = -EOPNOTSUPP; 79215d96753SBruno Randolf might_sleep(); 79315d96753SBruno Randolf if (local->ops->get_antenna) 79415d96753SBruno Randolf ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant); 79515d96753SBruno Randolf trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret); 79615d96753SBruno Randolf return ret; 79715d96753SBruno Randolf } 79815d96753SBruno Randolf 79921f83589SJohannes Berg static inline int drv_remain_on_channel(struct ieee80211_local *local, 80049884568SEliad Peller struct ieee80211_sub_if_data *sdata, 80121f83589SJohannes Berg struct ieee80211_channel *chan, 802d339d5caSIlan Peer unsigned int duration, 803d339d5caSIlan Peer enum ieee80211_roc_type type) 80421f83589SJohannes Berg { 80521f83589SJohannes Berg int ret; 80621f83589SJohannes Berg 80721f83589SJohannes Berg might_sleep(); 80821f83589SJohannes Berg 809d339d5caSIlan Peer trace_drv_remain_on_channel(local, sdata, chan, duration, type); 81049884568SEliad Peller ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, 811d339d5caSIlan Peer chan, duration, type); 81221f83589SJohannes Berg trace_drv_return_int(local, ret); 81321f83589SJohannes Berg 81421f83589SJohannes Berg return ret; 81521f83589SJohannes Berg } 81621f83589SJohannes Berg 81721f83589SJohannes Berg static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local) 81821f83589SJohannes Berg { 81921f83589SJohannes Berg int ret; 82021f83589SJohannes Berg 82121f83589SJohannes Berg might_sleep(); 82221f83589SJohannes Berg 82321f83589SJohannes Berg trace_drv_cancel_remain_on_channel(local); 82421f83589SJohannes Berg ret = local->ops->cancel_remain_on_channel(&local->hw); 82521f83589SJohannes Berg trace_drv_return_int(local, ret); 82621f83589SJohannes Berg 82721f83589SJohannes Berg return ret; 82821f83589SJohannes Berg } 82921f83589SJohannes Berg 83038c09159SJohn W. Linville static inline int drv_set_ringparam(struct ieee80211_local *local, 83138c09159SJohn W. Linville u32 tx, u32 rx) 83238c09159SJohn W. Linville { 83338c09159SJohn W. Linville int ret = -ENOTSUPP; 83438c09159SJohn W. Linville 83538c09159SJohn W. Linville might_sleep(); 83638c09159SJohn W. Linville 83738c09159SJohn W. Linville trace_drv_set_ringparam(local, tx, rx); 83838c09159SJohn W. Linville if (local->ops->set_ringparam) 83938c09159SJohn W. Linville ret = local->ops->set_ringparam(&local->hw, tx, rx); 84038c09159SJohn W. Linville trace_drv_return_int(local, ret); 84138c09159SJohn W. Linville 84238c09159SJohn W. Linville return ret; 84338c09159SJohn W. Linville } 84438c09159SJohn W. Linville 84538c09159SJohn W. Linville static inline void drv_get_ringparam(struct ieee80211_local *local, 84638c09159SJohn W. Linville u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) 84738c09159SJohn W. Linville { 84838c09159SJohn W. Linville might_sleep(); 84938c09159SJohn W. Linville 85038c09159SJohn W. Linville trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max); 85138c09159SJohn W. Linville if (local->ops->get_ringparam) 85238c09159SJohn W. Linville local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max); 85338c09159SJohn W. Linville trace_drv_return_void(local); 85438c09159SJohn W. Linville } 85538c09159SJohn W. Linville 856e8306f98SVivek Natarajan static inline bool drv_tx_frames_pending(struct ieee80211_local *local) 857e8306f98SVivek Natarajan { 858e8306f98SVivek Natarajan bool ret = false; 859e8306f98SVivek Natarajan 860e8306f98SVivek Natarajan might_sleep(); 861e8306f98SVivek Natarajan 862e8306f98SVivek Natarajan trace_drv_tx_frames_pending(local); 863e8306f98SVivek Natarajan if (local->ops->tx_frames_pending) 864e8306f98SVivek Natarajan ret = local->ops->tx_frames_pending(&local->hw); 865e8306f98SVivek Natarajan trace_drv_return_bool(local, ret); 866e8306f98SVivek Natarajan 867e8306f98SVivek Natarajan return ret; 868e8306f98SVivek Natarajan } 869bdbfd6b5SSujith Manoharan 870bdbfd6b5SSujith Manoharan static inline int drv_set_bitrate_mask(struct ieee80211_local *local, 871bdbfd6b5SSujith Manoharan struct ieee80211_sub_if_data *sdata, 872bdbfd6b5SSujith Manoharan const struct cfg80211_bitrate_mask *mask) 873bdbfd6b5SSujith Manoharan { 874bdbfd6b5SSujith Manoharan int ret = -EOPNOTSUPP; 875bdbfd6b5SSujith Manoharan 876bdbfd6b5SSujith Manoharan might_sleep(); 877bdbfd6b5SSujith Manoharan 878f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 879f6837ba8SJohannes Berg return -EIO; 8807b7eab6fSJohannes Berg 881bdbfd6b5SSujith Manoharan trace_drv_set_bitrate_mask(local, sdata, mask); 882bdbfd6b5SSujith Manoharan if (local->ops->set_bitrate_mask) 883bdbfd6b5SSujith Manoharan ret = local->ops->set_bitrate_mask(&local->hw, 884bdbfd6b5SSujith Manoharan &sdata->vif, mask); 885bdbfd6b5SSujith Manoharan trace_drv_return_int(local, ret); 886bdbfd6b5SSujith Manoharan 887bdbfd6b5SSujith Manoharan return ret; 888bdbfd6b5SSujith Manoharan } 889bdbfd6b5SSujith Manoharan 890c68f4b89SJohannes Berg static inline void drv_set_rekey_data(struct ieee80211_local *local, 891c68f4b89SJohannes Berg struct ieee80211_sub_if_data *sdata, 892c68f4b89SJohannes Berg struct cfg80211_gtk_rekey_data *data) 893c68f4b89SJohannes Berg { 894f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 895f6837ba8SJohannes Berg return; 8967b7eab6fSJohannes Berg 897c68f4b89SJohannes Berg trace_drv_set_rekey_data(local, sdata, data); 898c68f4b89SJohannes Berg if (local->ops->set_rekey_data) 899c68f4b89SJohannes Berg local->ops->set_rekey_data(&local->hw, &sdata->vif, data); 900c68f4b89SJohannes Berg trace_drv_return_void(local); 901c68f4b89SJohannes Berg } 902c68f4b89SJohannes Berg 903615f7b9bSMeenakshi Venkataraman static inline void drv_rssi_callback(struct ieee80211_local *local, 904887da917SEmmanuel Grumbach struct ieee80211_sub_if_data *sdata, 905615f7b9bSMeenakshi Venkataraman const enum ieee80211_rssi_event event) 906615f7b9bSMeenakshi Venkataraman { 907887da917SEmmanuel Grumbach trace_drv_rssi_callback(local, sdata, event); 908615f7b9bSMeenakshi Venkataraman if (local->ops->rssi_callback) 909887da917SEmmanuel Grumbach local->ops->rssi_callback(&local->hw, &sdata->vif, event); 910615f7b9bSMeenakshi Venkataraman trace_drv_return_void(local); 911615f7b9bSMeenakshi Venkataraman } 9124049e09aSJohannes Berg 9134049e09aSJohannes Berg static inline void 9144049e09aSJohannes Berg drv_release_buffered_frames(struct ieee80211_local *local, 9154049e09aSJohannes Berg struct sta_info *sta, u16 tids, int num_frames, 9164049e09aSJohannes Berg enum ieee80211_frame_release_type reason, 9174049e09aSJohannes Berg bool more_data) 9184049e09aSJohannes Berg { 9194049e09aSJohannes Berg trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames, 9204049e09aSJohannes Berg reason, more_data); 9214049e09aSJohannes Berg if (local->ops->release_buffered_frames) 9224049e09aSJohannes Berg local->ops->release_buffered_frames(&local->hw, &sta->sta, tids, 9234049e09aSJohannes Berg num_frames, reason, 9244049e09aSJohannes Berg more_data); 9254049e09aSJohannes Berg trace_drv_return_void(local); 9264049e09aSJohannes Berg } 92740b96408SJohannes Berg 92840b96408SJohannes Berg static inline void 92940b96408SJohannes Berg drv_allow_buffered_frames(struct ieee80211_local *local, 93040b96408SJohannes Berg struct sta_info *sta, u16 tids, int num_frames, 93140b96408SJohannes Berg enum ieee80211_frame_release_type reason, 93240b96408SJohannes Berg bool more_data) 93340b96408SJohannes Berg { 93440b96408SJohannes Berg trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames, 93540b96408SJohannes Berg reason, more_data); 93640b96408SJohannes Berg if (local->ops->allow_buffered_frames) 93740b96408SJohannes Berg local->ops->allow_buffered_frames(&local->hw, &sta->sta, 93840b96408SJohannes Berg tids, num_frames, reason, 93940b96408SJohannes Berg more_data); 94040b96408SJohannes Berg trace_drv_return_void(local); 94140b96408SJohannes Berg } 94266572cfcSVictor Goldenshtein 94366572cfcSVictor Goldenshtein static inline int drv_get_rssi(struct ieee80211_local *local, 94466572cfcSVictor Goldenshtein struct ieee80211_sub_if_data *sdata, 94566572cfcSVictor Goldenshtein struct ieee80211_sta *sta, 94666572cfcSVictor Goldenshtein s8 *rssi_dbm) 94766572cfcSVictor Goldenshtein { 94866572cfcSVictor Goldenshtein int ret; 94966572cfcSVictor Goldenshtein 95066572cfcSVictor Goldenshtein might_sleep(); 95166572cfcSVictor Goldenshtein 95266572cfcSVictor Goldenshtein ret = local->ops->get_rssi(&local->hw, &sdata->vif, sta, rssi_dbm); 95366572cfcSVictor Goldenshtein trace_drv_get_rssi(local, sta, *rssi_dbm, ret); 95466572cfcSVictor Goldenshtein 95566572cfcSVictor Goldenshtein return ret; 95666572cfcSVictor Goldenshtein } 957a1845fc7SJohannes Berg 958a1845fc7SJohannes Berg static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, 959a1845fc7SJohannes Berg struct ieee80211_sub_if_data *sdata) 960a1845fc7SJohannes Berg { 961a1845fc7SJohannes Berg might_sleep(); 962a1845fc7SJohannes Berg 963f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 964f6837ba8SJohannes Berg return; 965a1845fc7SJohannes Berg WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); 966a1845fc7SJohannes Berg 967a1845fc7SJohannes Berg trace_drv_mgd_prepare_tx(local, sdata); 968a1845fc7SJohannes Berg if (local->ops->mgd_prepare_tx) 969a1845fc7SJohannes Berg local->ops->mgd_prepare_tx(&local->hw, &sdata->vif); 970a1845fc7SJohannes Berg trace_drv_return_void(local); 971a1845fc7SJohannes Berg } 972c3645eacSMichal Kazior 973ee10f2c7SArik Nemtsov static inline void 974ee10f2c7SArik Nemtsov drv_mgd_protect_tdls_discover(struct ieee80211_local *local, 975ee10f2c7SArik Nemtsov struct ieee80211_sub_if_data *sdata) 976ee10f2c7SArik Nemtsov { 977ee10f2c7SArik Nemtsov might_sleep(); 978ee10f2c7SArik Nemtsov 979ee10f2c7SArik Nemtsov if (!check_sdata_in_driver(sdata)) 980ee10f2c7SArik Nemtsov return; 981ee10f2c7SArik Nemtsov WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); 982ee10f2c7SArik Nemtsov 983ee10f2c7SArik Nemtsov trace_drv_mgd_protect_tdls_discover(local, sdata); 984ee10f2c7SArik Nemtsov if (local->ops->mgd_protect_tdls_discover) 985ee10f2c7SArik Nemtsov local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif); 986ee10f2c7SArik Nemtsov trace_drv_return_void(local); 987ee10f2c7SArik Nemtsov } 988ee10f2c7SArik Nemtsov 989c3645eacSMichal Kazior static inline int drv_add_chanctx(struct ieee80211_local *local, 990c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 991c3645eacSMichal Kazior { 992c3645eacSMichal Kazior int ret = -EOPNOTSUPP; 993c3645eacSMichal Kazior 994c3645eacSMichal Kazior trace_drv_add_chanctx(local, ctx); 995c3645eacSMichal Kazior if (local->ops->add_chanctx) 996c3645eacSMichal Kazior ret = local->ops->add_chanctx(&local->hw, &ctx->conf); 997c3645eacSMichal Kazior trace_drv_return_int(local, ret); 9988a61af65SJohannes Berg if (!ret) 9998a61af65SJohannes Berg ctx->driver_present = true; 1000c3645eacSMichal Kazior 1001c3645eacSMichal Kazior return ret; 1002c3645eacSMichal Kazior } 1003c3645eacSMichal Kazior 1004c3645eacSMichal Kazior static inline void drv_remove_chanctx(struct ieee80211_local *local, 1005c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1006c3645eacSMichal Kazior { 1007f6837ba8SJohannes Berg if (WARN_ON(!ctx->driver_present)) 1008f6837ba8SJohannes Berg return; 1009f6837ba8SJohannes Berg 1010c3645eacSMichal Kazior trace_drv_remove_chanctx(local, ctx); 1011c3645eacSMichal Kazior if (local->ops->remove_chanctx) 1012c3645eacSMichal Kazior local->ops->remove_chanctx(&local->hw, &ctx->conf); 1013c3645eacSMichal Kazior trace_drv_return_void(local); 10148a61af65SJohannes Berg ctx->driver_present = false; 1015c3645eacSMichal Kazior } 1016c3645eacSMichal Kazior 1017c3645eacSMichal Kazior static inline void drv_change_chanctx(struct ieee80211_local *local, 1018c3645eacSMichal Kazior struct ieee80211_chanctx *ctx, 1019c3645eacSMichal Kazior u32 changed) 1020c3645eacSMichal Kazior { 1021c3645eacSMichal Kazior trace_drv_change_chanctx(local, ctx, changed); 10228a61af65SJohannes Berg if (local->ops->change_chanctx) { 10238a61af65SJohannes Berg WARN_ON_ONCE(!ctx->driver_present); 1024c3645eacSMichal Kazior local->ops->change_chanctx(&local->hw, &ctx->conf, changed); 10258a61af65SJohannes Berg } 1026c3645eacSMichal Kazior trace_drv_return_void(local); 1027c3645eacSMichal Kazior } 1028c3645eacSMichal Kazior 1029c3645eacSMichal Kazior static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, 1030c3645eacSMichal Kazior struct ieee80211_sub_if_data *sdata, 1031c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1032c3645eacSMichal Kazior { 1033c3645eacSMichal Kazior int ret = 0; 1034c3645eacSMichal Kazior 1035f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1036f6837ba8SJohannes Berg return -EIO; 1037c3645eacSMichal Kazior 1038c3645eacSMichal Kazior trace_drv_assign_vif_chanctx(local, sdata, ctx); 10398a61af65SJohannes Berg if (local->ops->assign_vif_chanctx) { 10408a61af65SJohannes Berg WARN_ON_ONCE(!ctx->driver_present); 1041c3645eacSMichal Kazior ret = local->ops->assign_vif_chanctx(&local->hw, 1042c3645eacSMichal Kazior &sdata->vif, 1043c3645eacSMichal Kazior &ctx->conf); 10448a61af65SJohannes Berg } 1045c3645eacSMichal Kazior trace_drv_return_int(local, ret); 1046c3645eacSMichal Kazior 1047c3645eacSMichal Kazior return ret; 1048c3645eacSMichal Kazior } 1049c3645eacSMichal Kazior 1050c3645eacSMichal Kazior static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, 1051c3645eacSMichal Kazior struct ieee80211_sub_if_data *sdata, 1052c3645eacSMichal Kazior struct ieee80211_chanctx *ctx) 1053c3645eacSMichal Kazior { 1054f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1055f6837ba8SJohannes Berg return; 1056c3645eacSMichal Kazior 1057c3645eacSMichal Kazior trace_drv_unassign_vif_chanctx(local, sdata, ctx); 10588a61af65SJohannes Berg if (local->ops->unassign_vif_chanctx) { 10598a61af65SJohannes Berg WARN_ON_ONCE(!ctx->driver_present); 1060c3645eacSMichal Kazior local->ops->unassign_vif_chanctx(&local->hw, 1061c3645eacSMichal Kazior &sdata->vif, 1062c3645eacSMichal Kazior &ctx->conf); 10638a61af65SJohannes Berg } 1064c3645eacSMichal Kazior trace_drv_return_void(local); 1065c3645eacSMichal Kazior } 1066c3645eacSMichal Kazior 10671a5f0c13SLuciano Coelho static inline int 10681a5f0c13SLuciano Coelho drv_switch_vif_chanctx(struct ieee80211_local *local, 10691a5f0c13SLuciano Coelho struct ieee80211_vif_chanctx_switch *vifs, 10701a5f0c13SLuciano Coelho int n_vifs, 10711a5f0c13SLuciano Coelho enum ieee80211_chanctx_switch_mode mode) 10721a5f0c13SLuciano Coelho { 10731a5f0c13SLuciano Coelho int ret = 0; 10741a5f0c13SLuciano Coelho int i; 10751a5f0c13SLuciano Coelho 10761a5f0c13SLuciano Coelho if (!local->ops->switch_vif_chanctx) 10771a5f0c13SLuciano Coelho return -EOPNOTSUPP; 10781a5f0c13SLuciano Coelho 10791a5f0c13SLuciano Coelho for (i = 0; i < n_vifs; i++) { 10801a5f0c13SLuciano Coelho struct ieee80211_chanctx *new_ctx = 10811a5f0c13SLuciano Coelho container_of(vifs[i].new_ctx, 10821a5f0c13SLuciano Coelho struct ieee80211_chanctx, 10831a5f0c13SLuciano Coelho conf); 10841a5f0c13SLuciano Coelho struct ieee80211_chanctx *old_ctx = 10851a5f0c13SLuciano Coelho container_of(vifs[i].old_ctx, 10861a5f0c13SLuciano Coelho struct ieee80211_chanctx, 10871a5f0c13SLuciano Coelho conf); 10881a5f0c13SLuciano Coelho 10891a5f0c13SLuciano Coelho WARN_ON_ONCE(!old_ctx->driver_present); 10901a5f0c13SLuciano Coelho WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS && 10911a5f0c13SLuciano Coelho new_ctx->driver_present) || 10921a5f0c13SLuciano Coelho (mode == CHANCTX_SWMODE_REASSIGN_VIF && 10931a5f0c13SLuciano Coelho !new_ctx->driver_present)); 10941a5f0c13SLuciano Coelho } 10951a5f0c13SLuciano Coelho 10961a5f0c13SLuciano Coelho trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode); 10971a5f0c13SLuciano Coelho ret = local->ops->switch_vif_chanctx(&local->hw, 10981a5f0c13SLuciano Coelho vifs, n_vifs, mode); 10991a5f0c13SLuciano Coelho trace_drv_return_int(local, ret); 11001a5f0c13SLuciano Coelho 11011a5f0c13SLuciano Coelho if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { 11021a5f0c13SLuciano Coelho for (i = 0; i < n_vifs; i++) { 11031a5f0c13SLuciano Coelho struct ieee80211_chanctx *new_ctx = 11041a5f0c13SLuciano Coelho container_of(vifs[i].new_ctx, 11051a5f0c13SLuciano Coelho struct ieee80211_chanctx, 11061a5f0c13SLuciano Coelho conf); 11071a5f0c13SLuciano Coelho struct ieee80211_chanctx *old_ctx = 11081a5f0c13SLuciano Coelho container_of(vifs[i].old_ctx, 11091a5f0c13SLuciano Coelho struct ieee80211_chanctx, 11101a5f0c13SLuciano Coelho conf); 11111a5f0c13SLuciano Coelho 11121a5f0c13SLuciano Coelho new_ctx->driver_present = true; 11131a5f0c13SLuciano Coelho old_ctx->driver_present = false; 11141a5f0c13SLuciano Coelho } 11151a5f0c13SLuciano Coelho } 11161a5f0c13SLuciano Coelho 11171a5f0c13SLuciano Coelho return ret; 11181a5f0c13SLuciano Coelho } 11191a5f0c13SLuciano Coelho 11201041638fSJohannes Berg static inline int drv_start_ap(struct ieee80211_local *local, 11211041638fSJohannes Berg struct ieee80211_sub_if_data *sdata) 11221041638fSJohannes Berg { 11231041638fSJohannes Berg int ret = 0; 11241041638fSJohannes Berg 1125f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1126f6837ba8SJohannes Berg return -EIO; 11271041638fSJohannes Berg 11281041638fSJohannes Berg trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); 11291041638fSJohannes Berg if (local->ops->start_ap) 11301041638fSJohannes Berg ret = local->ops->start_ap(&local->hw, &sdata->vif); 11311041638fSJohannes Berg trace_drv_return_int(local, ret); 11321041638fSJohannes Berg return ret; 11331041638fSJohannes Berg } 11341041638fSJohannes Berg 11351041638fSJohannes Berg static inline void drv_stop_ap(struct ieee80211_local *local, 11361041638fSJohannes Berg struct ieee80211_sub_if_data *sdata) 11371041638fSJohannes Berg { 1138f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1139f6837ba8SJohannes Berg return; 11401041638fSJohannes Berg 11411041638fSJohannes Berg trace_drv_stop_ap(local, sdata); 11421041638fSJohannes Berg if (local->ops->stop_ap) 11431041638fSJohannes Berg local->ops->stop_ap(&local->hw, &sdata->vif); 11441041638fSJohannes Berg trace_drv_return_void(local); 11451041638fSJohannes Berg } 11461041638fSJohannes Berg 11479214ad7fSJohannes Berg static inline void drv_restart_complete(struct ieee80211_local *local) 11489214ad7fSJohannes Berg { 11499214ad7fSJohannes Berg might_sleep(); 11509214ad7fSJohannes Berg 11519214ad7fSJohannes Berg trace_drv_restart_complete(local); 11529214ad7fSJohannes Berg if (local->ops->restart_complete) 11539214ad7fSJohannes Berg local->ops->restart_complete(&local->hw); 11549214ad7fSJohannes Berg trace_drv_return_void(local); 11559214ad7fSJohannes Berg } 11569214ad7fSJohannes Berg 1157de5fad81SYoni Divinsky static inline void 1158de5fad81SYoni Divinsky drv_set_default_unicast_key(struct ieee80211_local *local, 1159de5fad81SYoni Divinsky struct ieee80211_sub_if_data *sdata, 1160de5fad81SYoni Divinsky int key_idx) 1161de5fad81SYoni Divinsky { 1162f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1163f6837ba8SJohannes Berg return; 1164de5fad81SYoni Divinsky 1165de5fad81SYoni Divinsky WARN_ON_ONCE(key_idx < -1 || key_idx > 3); 1166de5fad81SYoni Divinsky 1167de5fad81SYoni Divinsky trace_drv_set_default_unicast_key(local, sdata, key_idx); 1168de5fad81SYoni Divinsky if (local->ops->set_default_unicast_key) 1169de5fad81SYoni Divinsky local->ops->set_default_unicast_key(&local->hw, &sdata->vif, 1170de5fad81SYoni Divinsky key_idx); 1171de5fad81SYoni Divinsky trace_drv_return_void(local); 1172de5fad81SYoni Divinsky } 1173de5fad81SYoni Divinsky 1174a65240c1SJohannes Berg #if IS_ENABLED(CONFIG_IPV6) 1175a65240c1SJohannes Berg static inline void drv_ipv6_addr_change(struct ieee80211_local *local, 1176a65240c1SJohannes Berg struct ieee80211_sub_if_data *sdata, 1177a65240c1SJohannes Berg struct inet6_dev *idev) 1178a65240c1SJohannes Berg { 1179a65240c1SJohannes Berg trace_drv_ipv6_addr_change(local, sdata); 1180a65240c1SJohannes Berg if (local->ops->ipv6_addr_change) 1181a65240c1SJohannes Berg local->ops->ipv6_addr_change(&local->hw, &sdata->vif, idev); 1182a65240c1SJohannes Berg trace_drv_return_void(local); 1183a65240c1SJohannes Berg } 1184a65240c1SJohannes Berg #endif 1185a65240c1SJohannes Berg 118673da7d5bSSimon Wunderlich static inline void 118773da7d5bSSimon Wunderlich drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata, 118873da7d5bSSimon Wunderlich struct cfg80211_chan_def *chandef) 118973da7d5bSSimon Wunderlich { 119073da7d5bSSimon Wunderlich struct ieee80211_local *local = sdata->local; 119173da7d5bSSimon Wunderlich 119273da7d5bSSimon Wunderlich if (local->ops->channel_switch_beacon) { 119373da7d5bSSimon Wunderlich trace_drv_channel_switch_beacon(local, sdata, chandef); 119473da7d5bSSimon Wunderlich local->ops->channel_switch_beacon(&local->hw, &sdata->vif, 119573da7d5bSSimon Wunderlich chandef); 119673da7d5bSSimon Wunderlich } 119773da7d5bSSimon Wunderlich } 119873da7d5bSSimon Wunderlich 1199*6d027bccSLuciano Coelho static inline int 1200*6d027bccSLuciano Coelho drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata, 1201*6d027bccSLuciano Coelho struct ieee80211_channel_switch *ch_switch) 1202*6d027bccSLuciano Coelho { 1203*6d027bccSLuciano Coelho struct ieee80211_local *local = sdata->local; 1204*6d027bccSLuciano Coelho int ret = 0; 1205*6d027bccSLuciano Coelho 1206*6d027bccSLuciano Coelho if (!check_sdata_in_driver(sdata)) 1207*6d027bccSLuciano Coelho return -EIO; 1208*6d027bccSLuciano Coelho 1209*6d027bccSLuciano Coelho trace_drv_pre_channel_switch(local, sdata, ch_switch); 1210*6d027bccSLuciano Coelho if (local->ops->pre_channel_switch) 1211*6d027bccSLuciano Coelho ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif, 1212*6d027bccSLuciano Coelho ch_switch); 1213*6d027bccSLuciano Coelho trace_drv_return_int(local, ret); 1214*6d027bccSLuciano Coelho return ret; 1215*6d027bccSLuciano Coelho } 1216*6d027bccSLuciano Coelho 121755fff501SJohannes Berg static inline int drv_join_ibss(struct ieee80211_local *local, 121855fff501SJohannes Berg struct ieee80211_sub_if_data *sdata) 121955fff501SJohannes Berg { 122055fff501SJohannes Berg int ret = 0; 122155fff501SJohannes Berg 122255fff501SJohannes Berg might_sleep(); 1223f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1224f6837ba8SJohannes Berg return -EIO; 122555fff501SJohannes Berg 122655fff501SJohannes Berg trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); 122755fff501SJohannes Berg if (local->ops->join_ibss) 122855fff501SJohannes Berg ret = local->ops->join_ibss(&local->hw, &sdata->vif); 122955fff501SJohannes Berg trace_drv_return_int(local, ret); 123055fff501SJohannes Berg return ret; 123155fff501SJohannes Berg } 123255fff501SJohannes Berg 123355fff501SJohannes Berg static inline void drv_leave_ibss(struct ieee80211_local *local, 123455fff501SJohannes Berg struct ieee80211_sub_if_data *sdata) 123555fff501SJohannes Berg { 123655fff501SJohannes Berg might_sleep(); 1237f6837ba8SJohannes Berg if (!check_sdata_in_driver(sdata)) 1238f6837ba8SJohannes Berg return; 123955fff501SJohannes Berg 124055fff501SJohannes Berg trace_drv_leave_ibss(local, sdata); 124155fff501SJohannes Berg if (local->ops->leave_ibss) 124255fff501SJohannes Berg local->ops->leave_ibss(&local->hw, &sdata->vif); 124355fff501SJohannes Berg trace_drv_return_void(local); 124455fff501SJohannes Berg } 124555fff501SJohannes Berg 1246cca674d4SAntonio Quartulli static inline u32 drv_get_expected_throughput(struct ieee80211_local *local, 1247cca674d4SAntonio Quartulli struct ieee80211_sta *sta) 1248cca674d4SAntonio Quartulli { 1249cca674d4SAntonio Quartulli u32 ret = 0; 1250cca674d4SAntonio Quartulli 1251cca674d4SAntonio Quartulli trace_drv_get_expected_throughput(sta); 1252cca674d4SAntonio Quartulli if (local->ops->get_expected_throughput) 1253cca674d4SAntonio Quartulli ret = local->ops->get_expected_throughput(sta); 1254cca674d4SAntonio Quartulli trace_drv_return_u32(local, ret); 1255cca674d4SAntonio Quartulli 1256cca674d4SAntonio Quartulli return ret; 1257cca674d4SAntonio Quartulli } 1258cca674d4SAntonio Quartulli 125924487981SJohannes Berg #endif /* __MAC80211_DRIVER_OPS */ 1260