From c5c47e67bcd24638a059b1b5e9ec18c95f8634ca Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 27 Oct 2014 17:13:30 +0100 Subject: mac802154: rx: use tasklet instead workqueue Tasklets have much less overhead than workqueues. This patch also removes the heap allocation for the worker on receiving path. Like mac80211 we should prefer use a tasklet here instead a workqueue to getting fast out of interrupt context when ieee802154_rx_irqsafe is called by driver. Like wireless inside the tasklet context we should call netif_receive_skb instead netif_rx_ni anymore. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/main.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'net/mac802154/main.c') diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 3c0a824d24ac..ff0de0f990cb 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -222,6 +222,29 @@ static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries) return local->ops->set_frame_retries(&local->hw, retries); } +static void ieee802154_tasklet_handler(unsigned long data) +{ + struct ieee802154_local *local = (struct ieee802154_local *)data; + struct sk_buff *skb; + + while ((skb = skb_dequeue(&local->skb_queue))) { + switch (skb->pkt_type) { + case IEEE802154_RX_MSG: + /* Clear skb->pkt_type in order to not confuse kernel + * netstack. + */ + skb->pkt_type = 0; + ieee802154_rx(&local->hw, skb); + break; + default: + WARN(1, "mac802154: Packet is of unknown type %d\n", + skb->pkt_type); + kfree_skb(skb); + break; + } + } +} + struct ieee802154_hw * ieee802154_alloc_hw(size_t priv_data_len, struct ieee802154_ops *ops) { @@ -270,6 +293,12 @@ ieee802154_alloc_hw(size_t priv_data_len, struct ieee802154_ops *ops) INIT_LIST_HEAD(&local->interfaces); mutex_init(&local->iflist_mtx); + tasklet_init(&local->tasklet, + ieee802154_tasklet_handler, + (unsigned long)local); + + skb_queue_head_init(&local->skb_queue); + return &local->hw; } EXPORT_SYMBOL(ieee802154_alloc_hw); @@ -371,6 +400,7 @@ void ieee802154_unregister_hw(struct ieee802154_hw *hw) struct ieee802154_local *local = hw_to_local(hw); struct ieee802154_sub_if_data *sdata, *next; + tasklet_kill(&local->tasklet); flush_workqueue(local->workqueue); destroy_workqueue(local->workqueue); -- cgit v1.2.3