diff options
Diffstat (limited to 'net/mac802154')
-rw-r--r-- | net/mac802154/ieee802154_i.h | 4 | ||||
-rw-r--r-- | net/mac802154/iface.c | 2 | ||||
-rw-r--r-- | net/mac802154/main.c | 17 | ||||
-rw-r--r-- | net/mac802154/tx.c | 2 | ||||
-rw-r--r-- | net/mac802154/util.c | 32 |
5 files changed, 53 insertions, 4 deletions
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 69cb585e162f..c5b231047b60 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -20,6 +20,7 @@ #define __IEEE802154_I_H #include <linux/mutex.h> +#include <linux/hrtimer.h> #include <net/cfg802154.h> #include <net/mac802154.h> #include <net/ieee802154_netdev.h> @@ -51,6 +52,8 @@ struct ieee802154_local { */ struct workqueue_struct *workqueue; + struct hrtimer ifs_timer; + bool started; struct tasklet_struct tasklet; @@ -127,6 +130,7 @@ ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); void mac802154_wpan_setup(struct net_device *dev); netdev_tx_t ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer); /* MIB callbacks */ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val); diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index ec92b48d1b0b..feb064715d1f 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -246,6 +246,8 @@ static int mac802154_slave_close(struct net_device *dev) ASSERT_RTNL(); + hrtimer_cancel(&local->ifs_timer); + netif_stop_queue(dev); local->open_count--; diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 46c76e005446..0af1be64e8ad 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -125,6 +125,18 @@ void ieee802154_free_hw(struct ieee802154_hw *hw) } EXPORT_SYMBOL(ieee802154_free_hw); +static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy) +{ + /* TODO warn on empty symbol_duration + * Should be done when all drivers sets this value. + */ + + wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD * + wpan_phy->symbol_duration; + wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD * + wpan_phy->symbol_duration; +} + int ieee802154_register_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); @@ -138,8 +150,13 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) goto out; } + hrtimer_init(&local->ifs_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + local->ifs_timer.function = ieee802154_xmit_ifs_timer; + wpan_phy_set_dev(local->phy, local->hw.parent); + ieee802154_setup_wpan_phy_pib(local->phy); + rc = wpan_phy_register(local->phy); if (rc < 0) goto out_wq; diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index cc37b77f2632..c62e95695c78 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c @@ -60,7 +60,7 @@ static void ieee802154_xmit_worker(struct work_struct *work) if (res) goto err_tx; - ieee802154_xmit_complete(&local->hw, skb); + ieee802154_xmit_complete(&local->hw, skb, false); dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; diff --git a/net/mac802154/util.c b/net/mac802154/util.c index 9a04e4a8e50f..5fc979027919 100644 --- a/net/mac802154/util.c +++ b/net/mac802154/util.c @@ -50,9 +50,35 @@ void ieee802154_stop_queue(struct ieee802154_hw *hw) } EXPORT_SYMBOL(ieee802154_stop_queue); -void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb) +enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer) { - ieee802154_wake_queue(hw); - consume_skb(skb); + struct ieee802154_local *local = + container_of(timer, struct ieee802154_local, ifs_timer); + + ieee802154_wake_queue(&local->hw); + + return HRTIMER_NORESTART; +} + +void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, + bool ifs_handling) +{ + if (ifs_handling) { + struct ieee802154_local *local = hw_to_local(hw); + + if (skb->len > 18) + hrtimer_start(&local->ifs_timer, + ktime_set(0, hw->phy->lifs_period * NSEC_PER_USEC), + HRTIMER_MODE_REL); + else + hrtimer_start(&local->ifs_timer, + ktime_set(0, hw->phy->sifs_period * NSEC_PER_USEC), + HRTIMER_MODE_REL); + + consume_skb(skb); + } else { + ieee802154_wake_queue(hw); + consume_skb(skb); + } } EXPORT_SYMBOL(ieee802154_xmit_complete); |