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 <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 3c0a824..ff0de0f 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -222,6 +222,29 @@
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 @@
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 @@
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);