18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Authors: 58c2ecf20Sopenharmony_ci * Alexander Aring <aar@pengutronix.de> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Based on: net/mac80211/util.c 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "ieee802154_i.h" 118c2ecf20Sopenharmony_ci#include "driver-ops.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* privid for wpan_phys to determine whether they belong to us or not */ 148c2ecf20Sopenharmony_ciconst void *const mac802154_wpan_phy_privid = &mac802154_wpan_phy_privid; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_civoid ieee802154_wake_queue(struct ieee802154_hw *hw) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci struct ieee802154_local *local = hw_to_local(hw); 198c2ecf20Sopenharmony_ci struct ieee802154_sub_if_data *sdata; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci rcu_read_lock(); 228c2ecf20Sopenharmony_ci list_for_each_entry_rcu(sdata, &local->interfaces, list) { 238c2ecf20Sopenharmony_ci if (!sdata->dev) 248c2ecf20Sopenharmony_ci continue; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci netif_wake_queue(sdata->dev); 278c2ecf20Sopenharmony_ci } 288c2ecf20Sopenharmony_ci rcu_read_unlock(); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ieee802154_wake_queue); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_civoid ieee802154_stop_queue(struct ieee802154_hw *hw) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci struct ieee802154_local *local = hw_to_local(hw); 358c2ecf20Sopenharmony_ci struct ieee802154_sub_if_data *sdata; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci rcu_read_lock(); 388c2ecf20Sopenharmony_ci list_for_each_entry_rcu(sdata, &local->interfaces, list) { 398c2ecf20Sopenharmony_ci if (!sdata->dev) 408c2ecf20Sopenharmony_ci continue; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci netif_stop_queue(sdata->dev); 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci rcu_read_unlock(); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ieee802154_stop_queue); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cienum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct ieee802154_local *local = 518c2ecf20Sopenharmony_ci container_of(timer, struct ieee802154_local, ifs_timer); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci ieee802154_wake_queue(&local->hw); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return HRTIMER_NORESTART; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_civoid ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, 598c2ecf20Sopenharmony_ci bool ifs_handling) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci if (ifs_handling) { 628c2ecf20Sopenharmony_ci struct ieee802154_local *local = hw_to_local(hw); 638c2ecf20Sopenharmony_ci u8 max_sifs_size; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* If transceiver sets CRC on his own we need to use lifs 668c2ecf20Sopenharmony_ci * threshold len above 16 otherwise 18, because it's not 678c2ecf20Sopenharmony_ci * part of skb->len. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ci if (hw->flags & IEEE802154_HW_TX_OMIT_CKSUM) 708c2ecf20Sopenharmony_ci max_sifs_size = IEEE802154_MAX_SIFS_FRAME_SIZE - 718c2ecf20Sopenharmony_ci IEEE802154_FCS_LEN; 728c2ecf20Sopenharmony_ci else 738c2ecf20Sopenharmony_ci max_sifs_size = IEEE802154_MAX_SIFS_FRAME_SIZE; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (skb->len > max_sifs_size) 768c2ecf20Sopenharmony_ci hrtimer_start(&local->ifs_timer, 778c2ecf20Sopenharmony_ci hw->phy->lifs_period * NSEC_PER_USEC, 788c2ecf20Sopenharmony_ci HRTIMER_MODE_REL); 798c2ecf20Sopenharmony_ci else 808c2ecf20Sopenharmony_ci hrtimer_start(&local->ifs_timer, 818c2ecf20Sopenharmony_ci hw->phy->sifs_period * NSEC_PER_USEC, 828c2ecf20Sopenharmony_ci HRTIMER_MODE_REL); 838c2ecf20Sopenharmony_ci } else { 848c2ecf20Sopenharmony_ci ieee802154_wake_queue(hw); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci dev_consume_skb_any(skb); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ieee802154_xmit_complete); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_civoid ieee802154_stop_device(struct ieee802154_local *local) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci flush_workqueue(local->workqueue); 948c2ecf20Sopenharmony_ci hrtimer_cancel(&local->ifs_timer); 958c2ecf20Sopenharmony_ci drv_stop(local); 968c2ecf20Sopenharmony_ci} 97