Skip to contentSkip to conversation

ieee802154: rework transmit handling

PATCH In review Alexander Aring 2 participants 17 messages Oct 26, 2014

Subsystems (5)
lore
Share & tools
lore

Alexander Aring

author maintainer
#0 lore raw

v2 cover ieee802154: rework transmit handling

This series contains patches for reworking tx handling. Also add a workaround to hold the xmit context when sending frames. Additional add support for asynchronous xmit handling and change the at86rf230 to do a asynchronous xmit handling.

Moving functions and renaming are necessary for the mac80211 naming convention.

changes since v2:
- remove whitespace in PATCH 14/15 ("mac802154: tx: add comment at sync xmit callback")

Alexander Aring (15):
mac802154: tx: move xmit callback to tx file
mac802154: tx: remove kmalloc in xmit hotpath
mac802154: tx: squash multiple dereferencing
mac802154: tx: remove xmit channel context switch
mac802154: add netdev qeue helpers
mac802154: tx: use queue helpers in xmit worker
mac802154: tx: fix error handling while xmit
mac802154: tx: add support for xmit_async callback
mac802154: tx: don't allow if down while sync tx
mac802154: tx: use netdev print helpers
mac802154: tx: cleanup crc calculation
mac802154: tx: move stats tx increment
mac802154: tx: change naming convention
mac802154: tx: add comment at sync xmit callback
at86rf230: asynchronous xmit handling

 drivers/net/ieee802154/at86rf230.c |  42 +++++------
 drivers/net/ieee802154/cc2520.c    |   2 +-
 drivers/net/ieee802154/fakelb.c    |   2 +-
 drivers/net/ieee802154/mrf24j40.c  |   2 +-
 include/net/mac802154.h            |  28 +++++--
 net/mac802154/Makefile             |   2 +-
 net/mac802154/ieee802154_i.h       |   7 +-
 net/mac802154/iface.c              |  37 +---------
 net/mac802154/main.c               |   4 +-
 net/mac802154/monitor.c            |  29 +-------
 net/mac802154/tx.c                 | 145 ++++++++++++++++++++++---------------
 net/mac802154/util.c               |  55 ++++++++++++++
 12 files changed, 193 insertions(+), 162 deletions(-)
 create mode 100644 net/mac802154/util.c
Signature · 1 line
2.1.2
author maintainer
#1 lore raw

PATCH v2 1/15 mac802154: tx: move xmit callback to tx file

This patch moves the netdev xmit callback functions into the tx.c file.

---
 net/mac802154/ieee802154_i.h |  5 ++--
 net/mac802154/iface.c        | 35 --------------------------
 net/mac802154/monitor.c      | 27 --------------------
 net/mac802154/tx.c           | 59 ++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 59 insertions(+), 67 deletions(-)
net/mac802154/ieee802154_i.h +2 -3
index 7aae692..a9a9d8e 100644
@@ -121,12 +121,11 @@ int mac802154_slave_close(struct net_device *dev);
 
 void mac802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb);
 void mac802154_monitor_setup(struct net_device *dev);
+netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb, struct net_device *dev);
 
 void mac802154_wpans_rx(struct ieee802154_local *local, struct sk_buff *skb);
 void mac802154_wpan_setup(struct net_device *dev);
-
-netdev_tx_t mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb,
-			 u8 page, u8 chan);
+netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* MIB callbacks */
 void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val);
net/mac802154/iface.c +0 -35
index cdd661f..f14e436 100644
@@ -307,41 +307,6 @@ mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 	return sizeof(*addr);
 }
 
-static netdev_tx_t
-mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata;
-	u8 chan, page;
-	int rc;
-
-	sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
-	spin_lock_bh(&sdata->mib_lock);
-	chan = sdata->chan;
-	page = sdata->page;
-	spin_unlock_bh(&sdata->mib_lock);
-
-	if (chan == MAC802154_CHAN_NONE ||
-	    page >= WPAN_NUM_PAGES ||
-	    chan >= WPAN_NUM_CHANNELS) {
-		kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	rc = mac802154_llsec_encrypt(&sdata->sec, skb);
-	if (rc) {
-		pr_warn("encryption failed: %i\n", rc);
-		kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	skb->skb_iif = dev->ifindex;
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	return mac802154_tx(sdata->local, skb, page, chan);
-}
-
 static struct header_ops mac802154_header_ops = {
 	.create		= mac802154_header_create,
 	.parse		= mac802154_header_parse,
net/mac802154/monitor.c +0 -27
index f8ea6dc..cb9600bcc 100644
@@ -30,33 +30,6 @@
 
 #include "ieee802154_i.h"
 
-static netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb,
-					  struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata;
-	u8 chan, page;
-
-	sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
-	/* FIXME: locking */
-	chan = sdata->local->phy->current_channel;
-	page = sdata->local->phy->current_page;
-
-	if (chan == MAC802154_CHAN_NONE) /* not initialized */
-		return NETDEV_TX_OK;
-
-	if (WARN_ON(page >= WPAN_NUM_PAGES) ||
-	    WARN_ON(chan >= WPAN_NUM_CHANNELS))
-		return NETDEV_TX_OK;
-
-	skb->skb_iif = dev->ifindex;
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	return mac802154_tx(sdata->local, skb, page, chan);
-}
-
-
 void mac802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
 {
 	struct sk_buff *skb2;
net/mac802154/tx.c +57 -2

68 lines not on this page · raw message

Signature · 1 line
2.1.2
author maintainer
#2 lore raw

PATCH v2 2/15 mac802154: tx: remove kmalloc in xmit hotpath

In reply to Alexander Aring

This patch removes the kmalloc allocation for workqueue data. This patch replaces the kmalloc and uses the control block of skb. The control block has enough space and isn't use by any other layer in this case.

---
 net/mac802154/tx.c | 56 ++++++++++++++++++++++++++----------------------------
 1 file changed, 27 insertions(+), 29 deletions(-)
net/mac802154/tx.c +27 -29
index 2eb06c2..513e760 100644
@@ -30,7 +30,7 @@
 /* IEEE 802.15.4 transceivers can sleep during the xmit session, so process
  * packets through the workqueue.
  */
-struct xmit_work {
+struct wpan_xmit_cb {
 	struct sk_buff *skb;
 	struct work_struct work;
 	struct ieee802154_local *local;
@@ -38,50 +38,54 @@ struct xmit_work {
 	u8 page;
 };
 
+static inline struct wpan_xmit_cb *wpan_xmit_cb(const struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct wpan_xmit_cb));
+
+	return (struct wpan_xmit_cb *)skb->cb;
+}
+
 static void mac802154_xmit_worker(struct work_struct *work)
 {
-	struct xmit_work *xw = container_of(work, struct xmit_work, work);
+	struct wpan_xmit_cb *cb = container_of(work, struct wpan_xmit_cb, work);
 	struct ieee802154_sub_if_data *sdata;
 	int res;
 
-	mutex_lock(&xw->local->phy->pib_lock);
-	if (xw->local->phy->current_channel != xw->chan ||
-	    xw->local->phy->current_page != xw->page) {
-		res = xw->local->ops->set_channel(&xw->local->hw,
-						  xw->page,
-						  xw->chan);
+	mutex_lock(&cb->local->phy->pib_lock);
+	if (cb->local->phy->current_channel != cb->chan ||
+	    cb->local->phy->current_page != cb->page) {
+		res = cb->local->ops->set_channel(&cb->local->hw, cb->page,
+						  cb->chan);
 		if (res) {
 			pr_debug("set_channel failed\n");
 			goto out;
 		}
 
-		xw->local->phy->current_channel = xw->chan;
-		xw->local->phy->current_page = xw->page;
+		cb->local->phy->current_channel = cb->chan;
+		cb->local->phy->current_page = cb->page;
 	}
 
-	res = xw->local->ops->xmit(&xw->local->hw, xw->skb);
+	res = cb->local->ops->xmit(&cb->local->hw, cb->skb);
 	if (res)
 		pr_debug("transmission failed\n");
 
 out:
-	mutex_unlock(&xw->local->phy->pib_lock);
+	mutex_unlock(&cb->local->phy->pib_lock);
 
 	/* Restart the netif queue on each sub_if_data object. */
 	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &xw->local->interfaces, list)
+	list_for_each_entry_rcu(sdata, &cb->local->interfaces, list)
 		netif_wake_queue(sdata->dev);
 	rcu_read_unlock();
 
-	dev_kfree_skb(xw->skb);
-
-	kfree(xw);
+	dev_kfree_skb(cb->skb);
 }
 
 static netdev_tx_t mac802154_tx(struct ieee802154_local *local,
 				struct sk_buff *skb, u8 page, u8 chan)
 {
-	struct xmit_work *work;
 	struct ieee802154_sub_if_data *sdata;
+	struct wpan_xmit_cb *cb = wpan_xmit_cb(skb);
 
 	if (!(local->phy->channels_supported[page] & (1 << chan))) {
 		WARN_ON(1);
@@ -101,25 +105,19 @@ static netdev_tx_t mac802154_tx(struct ieee802154_local *local,
 	if (skb_cow_head(skb, local->hw.extra_tx_headroom))
 		goto err_tx;
 
-	work = kzalloc(sizeof(*work), GFP_ATOMIC);
-	if (!work) {
-		kfree_skb(skb);
-		return NETDEV_TX_BUSY;
-	}
-
 	/* Stop the netif queue on each sub_if_data object. */
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list)
 		netif_stop_queue(sdata->dev);
 	rcu_read_unlock();
 
-	INIT_WORK(&work->work, mac802154_xmit_worker);
-	work->skb = skb;
-	work->local = local;
-	work->page = page;
-	work->chan = chan;
+	INIT_WORK(&cb->work, mac802154_xmit_worker);
+	cb->skb = skb;
+	cb->local = local;
+	cb->page = page;
+	cb->chan = chan;
 
-	queue_work(local->workqueue, &work->work);
+	queue_work(local->workqueue, &cb->work);
 
 	return NETDEV_TX_OK;
 
Signature · 1 line
2.1.2
author maintainer
#3 lore raw

PATCH v2 3/15 mac802154: tx: squash multiple dereferencing

In reply to Alexander Aring

This patch introduce some new stack variables to avoid multiple dereferencing inside the xmit worker function.

---
 net/mac802154/tx.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
net/mac802154/tx.c +12 -11
index 513e760..d0ceb46 100644
@@ -48,37 +48,38 @@ static inline struct wpan_xmit_cb *wpan_xmit_cb(const struct sk_buff *skb)
 static void mac802154_xmit_worker(struct work_struct *work)
 {
 	struct wpan_xmit_cb *cb = container_of(work, struct wpan_xmit_cb, work);
+	struct ieee802154_local *local = cb->local;
 	struct ieee802154_sub_if_data *sdata;
+	struct sk_buff *skb = cb->skb;
 	int res;
 
-	mutex_lock(&cb->local->phy->pib_lock);
-	if (cb->local->phy->current_channel != cb->chan ||
-	    cb->local->phy->current_page != cb->page) {
-		res = cb->local->ops->set_channel(&cb->local->hw, cb->page,
-						  cb->chan);
+	mutex_lock(&local->phy->pib_lock);
+	if (local->phy->current_channel != cb->chan ||
+	    local->phy->current_page != cb->page) {
+		res = local->ops->set_channel(&local->hw, cb->page, cb->chan);
 		if (res) {
 			pr_debug("set_channel failed\n");
 			goto out;
 		}
 
-		cb->local->phy->current_channel = cb->chan;
-		cb->local->phy->current_page = cb->page;
+		local->phy->current_channel = cb->chan;
+		local->phy->current_page = cb->page;
 	}
 
-	res = cb->local->ops->xmit(&cb->local->hw, cb->skb);
+	res = local->ops->xmit(&local->hw, skb);
 	if (res)
 		pr_debug("transmission failed\n");
 
 out:
-	mutex_unlock(&cb->local->phy->pib_lock);
+	mutex_unlock(&local->phy->pib_lock);
 
 	/* Restart the netif queue on each sub_if_data object. */
 	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &cb->local->interfaces, list)
+	list_for_each_entry_rcu(sdata, &local->interfaces, list)
 		netif_wake_queue(sdata->dev);
 	rcu_read_unlock();
 
-	dev_kfree_skb(cb->skb);
+	dev_kfree_skb(skb);
 }
 
 static netdev_tx_t mac802154_tx(struct ieee802154_local *local,
Signature · 1 line
2.1.2
author maintainer
#4 lore raw

PATCH v2 4/15 mac802154: tx: remove xmit channel context switch

In reply to Alexander Aring

This patch removes the channel hopping feature before xmit. There are several issues to provide a real channel hopping (timing requirements, etc...).

We don't have any known kernelspace protocol which really use this feature. And I don't know an real user of this feature. We simply drop this feature now.

This patch removes also the hold of pib lock which isn't needed by any real driver xmit callback implementation.

---
 include/net/mac802154.h |  3 +--
 net/mac802154/tx.c      | 58 ++++---------------------------------------------
 2 files changed, 5 insertions(+), 56 deletions(-)
include/net/mac802154.h +1 -2
index b07d431..ba8ddff 100644
@@ -113,8 +113,7 @@ struct ieee802154_hw {
  *	  skb cntains the buffer starting from the IEEE 802.15.4 header.
  *	  The low-level driver should send the frame based on available
  *	  configuration.
- *	  This function should return zero or negative errno. Called with
- *	  pib_lock held.
+ *	  This function should return zero or negative errno.
  *
  * ed:    Handler that 802.15.4 module calls for Energy Detection.
  *	  This function should place the value for detected energy
net/mac802154/tx.c +4 -54

112 lines not on this page · raw message

Signature · 1 line
2.1.2
author maintainer
#5 lore raw

PATCH v2 5/15 mac802154: add netdev qeue helpers

In reply to Alexander Aring

This patch adds a new file net/mac802154/util.c which contains utility functions for drivers, etc. This file contains functions to start and stop queues for all virtual interfaces, this is useful for asynchronous handling by driver level.

---
 include/net/mac802154.h |  4 ++++
 net/mac802154/Makefile  |  2 +-
 net/mac802154/util.c    | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 net/mac802154/util.c
include/net/mac802154.h +4 -0
index ba8ddff..29af5c3 100644
@@ -190,4 +190,8 @@ void ieee802154_unregister_hw(struct ieee802154_hw *hw);
 void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
 			   u8 lqi);
 
+void ieee802154_wake_queue(struct ieee802154_hw *hw);
+void ieee802154_stop_queue(struct ieee802154_hw *hw);
+void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb);
+
 #endif /* NET_MAC802154_H */
net/mac802154/Makefile +1 -1
index 203f42d..e68deba 100644
@@ -1,5 +1,5 @@
 obj-$(CONFIG_MAC802154)	+= mac802154.o
 mac802154-objs		:= main.o rx.o tx.o mac_cmd.o mib.o \
-			   monitor.o iface.o llsec.o
+			   monitor.o iface.o llsec.o util.o
 
 ccflags-y += -D__CHECK_ENDIAN__
net/mac802154/util.c new file +55 -0

55 lines not on this page · raw message

Signature · 1 line
2.1.2
author maintainer
#6 lore raw

PATCH v2 6/15 mac802154: tx: use queue helpers in xmit worker

In reply to Alexander Aring

This patch uses the queue utility helpers inside the xmit worker of mac802154 subsystem.

---
 net/mac802154/tx.c | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)
net/mac802154/tx.c +2 -12
index be8deae..8e2f429 100644
@@ -47,7 +47,6 @@ static void mac802154_xmit_worker(struct work_struct *work)
 {
 	struct wpan_xmit_cb *cb = container_of(work, struct wpan_xmit_cb, work);
 	struct ieee802154_local *local = cb->local;
-	struct ieee802154_sub_if_data *sdata;
 	struct sk_buff *skb = cb->skb;
 	int res;
 
@@ -56,18 +55,12 @@ static void mac802154_xmit_worker(struct work_struct *work)
 		pr_debug("transmission failed\n");
 
 	/* Restart the netif queue on each sub_if_data object. */
-	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list)
-		netif_wake_queue(sdata->dev);
-	rcu_read_unlock();
-
-	dev_kfree_skb(skb);
+	ieee802154_xmit_complete(&local->hw, skb);
 }
 
 static netdev_tx_t
 mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 {
-	struct ieee802154_sub_if_data *sdata;
 	struct wpan_xmit_cb *cb = wpan_xmit_cb(skb);
 
 	mac802154_monitors_rx(local, skb);
@@ -84,10 +77,7 @@ mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 		goto err_tx;
 
 	/* Stop the netif queue on each sub_if_data object. */
-	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list)
-		netif_stop_queue(sdata->dev);
-	rcu_read_unlock();
+	ieee802154_stop_queue(&local->hw);
 
 	INIT_WORK(&cb->work, mac802154_xmit_worker);
 	cb->skb = skb;
Signature · 1 line
2.1.2
author maintainer
#7 lore raw

PATCH v2 7/15 mac802154: tx: fix error handling while xmit

In reply to Alexander Aring

In case of an error we should call kfree_skb instead of consume_skb which is called by ieee802154_xmit_complete function.

---
 net/mac802154/tx.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
net/mac802154/tx.c +8 -4
index 8e2f429..23139ca 100644
@@ -51,11 +51,15 @@ static void mac802154_xmit_worker(struct work_struct *work)
 	int res;
 
 	res = local->ops->xmit(&local->hw, skb);
-	if (res)
+	if (res) {
 		pr_debug("transmission failed\n");
-
-	/* Restart the netif queue on each sub_if_data object. */
-	ieee802154_xmit_complete(&local->hw, skb);
+		/* Restart the netif queue on each sub_if_data object. */
+		ieee802154_wake_queue(&local->hw);
+		kfree_skb(skb);
+	} else {
+		/* Restart the netif queue on each sub_if_data object. */
+		ieee802154_xmit_complete(&local->hw, skb);
+	}
 }
 
 static netdev_tx_t
Signature · 1 line
2.1.2
author maintainer
#8 lore raw

PATCH v2 8/15 mac802154: tx: add support for xmit_async callback

In reply to Alexander Aring

This patch renames the existsing xmit callback to xmit_sync and introduces an asynchronous xmit_async function. If ieee802154_ops doesn't provide the xmit_async callback, then we have a fallback to the xmit_sync callback.

---
 drivers/net/ieee802154/at86rf230.c |  2 +-
 drivers/net/ieee802154/cc2520.c    |  2 +-
 drivers/net/ieee802154/fakelb.c    |  2 +-
 drivers/net/ieee802154/mrf24j40.c  |  2 +-
 include/net/mac802154.h            | 17 ++++++++++++++---
 net/mac802154/main.c               |  4 ++--
 net/mac802154/tx.c                 | 20 +++++++++++++++-----
 7 files changed, 35 insertions(+), 14 deletions(-)
drivers/net/ieee802154/at86rf230.c +1 -1
index b0d68d7..06a3e90 100644
@@ -1237,7 +1237,7 @@ at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
 
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
-	.xmit = at86rf230_xmit,
+	.xmit_sync = at86rf230_xmit,
 	.ed = at86rf230_ed,
 	.set_channel = at86rf230_channel,
 	.start = at86rf230_start,
drivers/net/ieee802154/cc2520.c +1 -1
index b827e04..f6f07f4 100644
@@ -635,7 +635,7 @@ static struct ieee802154_ops cc2520_ops = {
 	.owner = THIS_MODULE,
 	.start = cc2520_start,
 	.stop = cc2520_stop,
-	.xmit = cc2520_tx,
+	.xmit_sync = cc2520_tx,
 	.ed = cc2520_ed,
 	.set_channel = cc2520_set_channel,
 	.set_hw_addr_filt = cc2520_filter,
drivers/net/ieee802154/fakelb.c +1 -1
index 51e3c58..db0703f 100644
@@ -131,7 +131,7 @@ fakelb_hw_stop(struct ieee802154_hw *hw) {
 
 static struct ieee802154_ops fakelb_ops = {
 	.owner = THIS_MODULE,
-	.xmit = fakelb_hw_xmit,
+	.xmit_sync = fakelb_hw_xmit,
 	.ed = fakelb_hw_ed,
 	.set_channel = fakelb_hw_channel,
 	.start = fakelb_hw_start,
drivers/net/ieee802154/mrf24j40.c +1 -1
index 2e267c5..3d775af 100644
@@ -581,7 +581,7 @@ out:
 
 static struct ieee802154_ops mrf24j40_ops = {
 	.owner = THIS_MODULE,
-	.xmit = mrf24j40_tx,
+	.xmit_sync = mrf24j40_tx,
 	.ed = mrf24j40_ed,
 	.start = mrf24j40_start,
 	.stop = mrf24j40_stop,
include/net/mac802154.h +14 -3
index 29af5c3..57b1202 100644
@@ -109,7 +109,16 @@ struct ieee802154_hw {
  * stop:  Handler that 802.15.4 module calls for device cleanup.
  *	  This function is called after the last interface is removed.
  *
- * xmit:  Handler that 802.15.4 module calls for each transmitted frame.
+ * xmit_sync:
+ *	  Handler that 802.15.4 module calls for each transmitted frame.
+ *	  skb cntains the buffer starting from the IEEE 802.15.4 header.
+ *	  The low-level driver should send the frame based on available
+ *	  configuration. This is called by a workqueue and useful for
+ *	  synchronous 802.15.4 drivers.
+ *	  This function should return zero or negative errno.
+ *
+ * xmit_async:
+ *	  Handler that 802.15.4 module calls for each transmitted frame.
  *	  skb cntains the buffer starting from the IEEE 802.15.4 header.
  *	  The low-level driver should send the frame based on available
  *	  configuration.
@@ -160,8 +169,10 @@ struct ieee802154_ops {
 	struct module	*owner;
 	int		(*start)(struct ieee802154_hw *hw);
 	void		(*stop)(struct ieee802154_hw *hw);
-	int		(*xmit)(struct ieee802154_hw *hw,
-				struct sk_buff *skb);
+	int		(*xmit_sync)(struct ieee802154_hw *hw,
+				     struct sk_buff *skb);
+	int		(*xmit_async)(struct ieee802154_hw *hw,
+				      struct sk_buff *skb);
 	int		(*ed)(struct ieee802154_hw *hw, u8 *level);
 	int		(*set_channel)(struct ieee802154_hw *hw,
 				       int page,
net/mac802154/main.c +2 -2
index 0e9a6a2..3c0a824 100644
@@ -229,8 +229,8 @@ ieee802154_alloc_hw(size_t priv_data_len, struct ieee802154_ops *ops)
 	struct ieee802154_local *local;
 	size_t priv_size;
 
-	if (!ops || !ops->xmit || !ops->ed || !ops->start ||
-	    !ops->stop || !ops->set_channel) {
+	if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed ||
+	    !ops->start || !ops->stop || !ops->set_channel) {
 		pr_err("undefined IEEE802.15.4 device operations\n");
 		return NULL;
 	}
net/mac802154/tx.c +15 -5
index 23139ca..1a4f6d9 100644
@@ -50,7 +50,7 @@ static void mac802154_xmit_worker(struct work_struct *work)
 	struct sk_buff *skb = cb->skb;
 	int res;
 
-	res = local->ops->xmit(&local->hw, skb);
+	res = local->ops->xmit_sync(&local->hw, skb);
 	if (res) {
 		pr_debug("transmission failed\n");
 		/* Restart the netif queue on each sub_if_data object. */
@@ -66,6 +66,7 @@ static netdev_tx_t
 mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 {
 	struct wpan_xmit_cb *cb = wpan_xmit_cb(skb);
+	int ret;
 
 	mac802154_monitors_rx(local, skb);
 
@@ -83,11 +84,20 @@ mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	/* Stop the netif queue on each sub_if_data object. */
 	ieee802154_stop_queue(&local->hw);
 
-	INIT_WORK(&cb->work, mac802154_xmit_worker);
-	cb->skb = skb;
-	cb->local = local;
+	/* async is priority, otherwise sync is fallback */
+	if (local->ops->xmit_async) {
+		ret = local->ops->xmit_async(&local->hw, skb);
+		if (ret) {
+			ieee802154_wake_queue(&local->hw);
+			goto err_tx;
+		}
+	} else {
+		INIT_WORK(&cb->work, mac802154_xmit_worker);
+		cb->skb = skb;
+		cb->local = local;
 
-	queue_work(local->workqueue, &cb->work);
+		queue_work(local->workqueue, &cb->work);
+	}
 
 	return NETDEV_TX_OK;
 
Signature · 1 line
2.1.2
author maintainer
#9 lore raw

PATCH v2 9/15 mac802154: tx: don't allow if down while sync tx

In reply to Alexander Aring

This patch holds rtnl lock while sync xmit inside of workqueue. Otherwise we could down the interface while worker xmit handling.

---
 net/mac802154/tx.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)
net/mac802154/tx.c +22 -9
index 1a4f6d9..4439041 100644
@@ -21,6 +21,7 @@
 #include <linux/if_arp.h>
 #include <linux/crc-ccitt.h>
 
+#include <net/rtnetlink.h>
 #include <net/ieee802154_netdev.h>
 #include <net/mac802154.h>
 #include <net/cfg802154.h>
@@ -50,16 +51,28 @@ static void mac802154_xmit_worker(struct work_struct *work)
 	struct sk_buff *skb = cb->skb;
 	int res;
 
+	rtnl_lock();
+
+	/* check if ifdown occurred while schedule */
+	if (!netif_running(skb->dev))
+		goto err_tx;
+
 	res = local->ops->xmit_sync(&local->hw, skb);
-	if (res) {
-		pr_debug("transmission failed\n");
-		/* Restart the netif queue on each sub_if_data object. */
-		ieee802154_wake_queue(&local->hw);
-		kfree_skb(skb);
-	} else {
-		/* Restart the netif queue on each sub_if_data object. */
-		ieee802154_xmit_complete(&local->hw, skb);
-	}
+	if (res)
+		goto err_tx;
+
+	ieee802154_xmit_complete(&local->hw, skb);
+
+	rtnl_unlock();
+
+	return;
+
+err_tx:
+	/* Restart the netif queue on each sub_if_data object. */
+	ieee802154_wake_queue(&local->hw);
+	rtnl_unlock();
+	kfree_skb(skb);
+	pr_debug("transmission failed\n");
 }
 
 static netdev_tx_t
Signature · 1 line
2.1.2
author maintainer
#10 lore raw

PATCH v2 10/15 mac802154: tx: use netdev print helpers

In reply to Alexander Aring

This patch replace the pr_foo printout function to netdev_foo printout function. Inside the xmit handling, the interface is already known.

---
 net/mac802154/tx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/mac802154/tx.c +2 -2
index 4439041..d39c7d9 100644
@@ -72,7 +72,7 @@ err_tx:
 	ieee802154_wake_queue(&local->hw);
 	rtnl_unlock();
 	kfree_skb(skb);
-	pr_debug("transmission failed\n");
+	netdev_dbg(skb->dev, "transmission failed\n");
 }
 
 static netdev_tx_t
@@ -137,7 +137,7 @@ netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	rc = mac802154_llsec_encrypt(&sdata->sec, skb);
 	if (rc) {
-		pr_warn("encryption failed: %i\n", rc);
+		netdev_warn(dev, "encryption failed: %i\n", rc);
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
Signature · 1 line
2.1.2
author maintainer
#11 lore raw

PATCH v2 11/15 mac802154: tx: cleanup crc calculation

In reply to Alexander Aring
---
 net/mac802154/tx.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
net/mac802154/tx.c +2 -4
index d39c7d9..70fd226 100644
@@ -84,11 +84,9 @@ mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	mac802154_monitors_rx(local, skb);
 
 	if (!(local->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
-		u16 crc = crc_ccitt(0, skb->data, skb->len);
-		u8 *data = skb_put(skb, 2);
+		__le16 crc = cpu_to_le16(crc_ccitt(0, skb->data, skb->len));
 
-		data[0] = crc & 0xff;
-		data[1] = crc >> 8;
+		memcpy(skb_put(skb, 2), &crc, 2);
 	}
 
 	if (skb_cow_head(skb, local->hw.extra_tx_headroom))
Signature · 1 line
2.1.2
author maintainer
#12 lore raw

PATCH v2 12/15 mac802154: tx: move stats tx increment

In reply to Alexander Aring

This patch moves the stats increment of successful transmitted packets in the right place when the skb was really successful transmitted.

---
 net/mac802154/tx.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)
net/mac802154/tx.c +10 -6
index 70fd226..fe105d4 100644
@@ -49,12 +49,13 @@ static void mac802154_xmit_worker(struct work_struct *work)
 	struct wpan_xmit_cb *cb = container_of(work, struct wpan_xmit_cb, work);
 	struct ieee802154_local *local = cb->local;
 	struct sk_buff *skb = cb->skb;
+	struct net_device *dev = skb->dev;
 	int res;
 
 	rtnl_lock();
 
 	/* check if ifdown occurred while schedule */
-	if (!netif_running(skb->dev))
+	if (!netif_running(dev))
 		goto err_tx;
 
 	res = local->ops->xmit_sync(&local->hw, skb);
@@ -63,6 +64,9 @@ static void mac802154_xmit_worker(struct work_struct *work)
 
 	ieee802154_xmit_complete(&local->hw, skb);
 
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
 	rtnl_unlock();
 
 	return;
@@ -72,13 +76,14 @@ err_tx:
 	ieee802154_wake_queue(&local->hw);
 	rtnl_unlock();
 	kfree_skb(skb);
-	netdev_dbg(skb->dev, "transmission failed\n");
+	netdev_dbg(dev, "transmission failed\n");
 }
 
 static netdev_tx_t
 mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 {
 	struct wpan_xmit_cb *cb = wpan_xmit_cb(skb);
+	struct net_device *dev = skb->dev;
 	int ret;
 
 	mac802154_monitors_rx(local, skb);
@@ -102,6 +107,9 @@ mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 			ieee802154_wake_queue(&local->hw);
 			goto err_tx;
 		}
+
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += skb->len;
 	} else {
 		INIT_WORK(&cb->work, mac802154_xmit_worker);
 		cb->skb = skb;
@@ -122,8 +130,6 @@ netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 
 	skb->skb_iif = dev->ifindex;
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
 
 	return mac802154_tx(sdata->local, skb);
 }
@@ -141,8 +147,6 @@ netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	skb->skb_iif = dev->ifindex;
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
 
 	return mac802154_tx(sdata->local, skb);
 }
Signature · 1 line
2.1.2
author maintainer
#13 lore raw

PATCH v2 13/15 mac802154: tx: change naming convention

In reply to Alexander Aring

This patch changes the naming convention of the tx functions like mac80211. Just with an 802154 instead 80211 inside the name.

---
 net/mac802154/ieee802154_i.h |  6 ++++--
 net/mac802154/iface.c        |  2 +-
 net/mac802154/monitor.c      |  2 +-
 net/mac802154/tx.c           | 30 +++++++++++++++++-------------
 4 files changed, 23 insertions(+), 17 deletions(-)
net/mac802154/ieee802154_i.h +4 -2
index a9a9d8e..ef29c10 100644
@@ -121,11 +121,13 @@ int mac802154_slave_close(struct net_device *dev);
 
 void mac802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb);
 void mac802154_monitor_setup(struct net_device *dev);
-netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb, struct net_device *dev);
+netdev_tx_t
+ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 void mac802154_wpans_rx(struct ieee802154_local *local, struct sk_buff *skb);
 void mac802154_wpan_setup(struct net_device *dev);
-netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev);
+netdev_tx_t
+ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* MIB callbacks */
 void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val);
net/mac802154/iface.c +1 -1
index f14e436..be45dc9 100644
@@ -315,7 +315,7 @@ static struct header_ops mac802154_header_ops = {
 static const struct net_device_ops mac802154_wpan_ops = {
 	.ndo_open		= mac802154_wpan_open,
 	.ndo_stop		= mac802154_slave_close,
-	.ndo_start_xmit		= mac802154_wpan_xmit,
+	.ndo_start_xmit		= ieee802154_subif_start_xmit,
 	.ndo_do_ioctl		= mac802154_wpan_ioctl,
 	.ndo_set_mac_address	= mac802154_wpan_mac_addr,
 };
net/mac802154/monitor.c +1 -1
index cb9600bcc..5758322 100644
@@ -58,7 +58,7 @@ void mac802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
 static const struct net_device_ops mac802154_monitor_ops = {
 	.ndo_open		= mac802154_slave_open,
 	.ndo_stop		= mac802154_slave_close,
-	.ndo_start_xmit		= mac802154_monitor_xmit,
+	.ndo_start_xmit		= ieee802154_monitor_start_xmit,
 };
 
 void mac802154_monitor_setup(struct net_device *dev)
net/mac802154/tx.c +17 -13
index fe105d4..74882c7 100644
@@ -31,22 +31,24 @@
 /* IEEE 802.15.4 transceivers can sleep during the xmit session, so process
  * packets through the workqueue.
  */
-struct wpan_xmit_cb {
+struct ieee802154_xmit_cb {
 	struct sk_buff *skb;
 	struct work_struct work;
 	struct ieee802154_local *local;
 };
 
-static inline struct wpan_xmit_cb *wpan_xmit_cb(const struct sk_buff *skb)
+static inline struct ieee802154_xmit_cb *
+ieee802154_xmit_cb(const struct sk_buff *skb)
 {
-	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct wpan_xmit_cb));
+	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ieee802154_xmit_cb));
 
-	return (struct wpan_xmit_cb *)skb->cb;
+	return (struct ieee802154_xmit_cb *)skb->cb;
 }
 
-static void mac802154_xmit_worker(struct work_struct *work)
+static void ieee802154_xmit_worker(struct work_struct *work)
 {
-	struct wpan_xmit_cb *cb = container_of(work, struct wpan_xmit_cb, work);
+	struct ieee802154_xmit_cb *cb =
+		container_of(work, struct ieee802154_xmit_cb, work);
 	struct ieee802154_local *local = cb->local;
 	struct sk_buff *skb = cb->skb;
 	struct net_device *dev = skb->dev;
@@ -80,9 +82,9 @@ err_tx:
 }
 
 static netdev_tx_t
-mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
+ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 {
-	struct wpan_xmit_cb *cb = wpan_xmit_cb(skb);
+	struct ieee802154_xmit_cb *cb = ieee802154_xmit_cb(skb);
 	struct net_device *dev = skb->dev;
 	int ret;
 
@@ -111,7 +113,7 @@ mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 		dev->stats.tx_packets++;
 		dev->stats.tx_bytes += skb->len;
 	} else {
-		INIT_WORK(&cb->work, mac802154_xmit_worker);
+		INIT_WORK(&cb->work, ieee802154_xmit_worker);
 		cb->skb = skb;
 		cb->local = local;
 
@@ -125,16 +127,18 @@ err_tx:
 	return NETDEV_TX_OK;
 }
 
-netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb, struct net_device *dev)
+netdev_tx_t
+ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 
 	skb->skb_iif = dev->ifindex;
 
-	return mac802154_tx(sdata->local, skb);
+	return ieee802154_tx(sdata->local, skb);
 }
 
-netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
+netdev_tx_t
+ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 	int rc;
@@ -148,5 +152,5 @@ netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	skb->skb_iif = dev->ifindex;
 
-	return mac802154_tx(sdata->local, skb);
+	return ieee802154_tx(sdata->local, skb);
 }
Signature · 1 line
2.1.2
author maintainer
#14 lore raw

PATCH v2 14/15 mac802154: tx: add comment at sync xmit callback

In reply to Alexander Aring

This patch adds a warning that xmit_sync callback is deprecated and should be removed soon. The 802.15.4 subsystem will not accept synced drivers anymore.

---
 include/net/mac802154.h | 4 ++++
 1 file changed, 4 insertions(+)
include/net/mac802154.h +4 -0
index 57b1202..942dd53 100644
@@ -117,6 +117,10 @@ struct ieee802154_hw {
  *	  synchronous 802.15.4 drivers.
  *	  This function should return zero or negative errno.
  *
+ *	  WARNING:
+ *	  This will be deprecated soon. We don't accept synced xmit callbacks
+ *	  drivers anymore.
+ *
  * xmit_async:
  *	  Handler that 802.15.4 module calls for each transmitted frame.
  *	  skb cntains the buffer starting from the IEEE 802.15.4 header.
Signature · 1 line
2.1.2
author maintainer
#15 lore raw

PATCH v2 15/15 at86rf230: asynchronous xmit handling

In reply to Alexander Aring

This patch converts the sync xmit handling into an async xmit handling. The driver was already prepared for this step, all other drivers need more work to implement a xmit_async function.

---
 drivers/net/ieee802154/at86rf230.c | 42 +++++++++++++++-----------------------
 1 file changed, 17 insertions(+), 25 deletions(-)
drivers/net/ieee802154/at86rf230.c +17 -25
index 06a3e90..0669783 100644
@@ -91,7 +91,6 @@ struct at86rf230_local {
 	bool is_tx;
 	/* spinlock for is_tx protection */
 	spinlock_t lock;
-	struct completion tx_complete;
 	struct sk_buff *tx_skb;
 	struct at86rf230_state_change tx;
 };
@@ -452,6 +451,7 @@ at86rf230_async_error_recover(void *context)
 	struct at86rf230_local *lp = ctx->lp;
 
 	at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false);
+	ieee802154_wake_queue(lp->hw);
 }
 
 static void
@@ -715,9 +715,23 @@ at86rf230_tx_complete(void *context)
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
+	struct sk_buff *skb = lp->tx_skb;
 
 	enable_irq(lp->spi->irq);
-	complete(&lp->tx_complete);
+
+	if (lp->max_frame_retries <= 0) {
+		/* Interfame spacing time, which is phy depend.
+		 * TODO
+		 * Move this handling in MAC 802.15.4 layer.
+		 * This is currently a workaround to avoid fragmenation issues.
+		 */
+		if (skb->len > 18)
+			udelay(lp->data->t_lifs);
+		else
+			udelay(lp->data->t_sifs);
+	}
+
+	ieee802154_xmit_complete(lp->hw, skb);
 }
 
 static void
@@ -975,7 +989,6 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 	struct at86rf230_state_change *ctx = &lp->tx;
 
 	void (*tx_complete)(void *context) = at86rf230_write_frame;
-	int rc;
 
 	lp->tx_skb = skb;
 
@@ -988,26 +1001,6 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 
 	at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false);
 
-	rc = wait_for_completion_interruptible_timeout(&lp->tx_complete,
-						       msecs_to_jiffies(lp->data->t_tx_timeout));
-	if (!rc) {
-		at86rf230_async_error(lp, ctx, -ETIMEDOUT);
-		return -ETIMEDOUT;
-	}
-
-	if (lp->max_frame_retries > 0)
-		return 0;
-
-	/* Interfame spacing time, which is phy depend.
-	 * TODO
-	 * Move this handling in MAC 802.15.4 layer.
-	 * This is currently a workaround to avoid fragmenation issues.
-	 */
-	if (skb->len > 18)
-		usleep_range(lp->data->t_lifs, lp->data->t_lifs + 10);
-	else
-		usleep_range(lp->data->t_sifs, lp->data->t_sifs + 10);
-
 	return 0;
 }
 
@@ -1237,7 +1230,7 @@ at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
 
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
-	.xmit_sync = at86rf230_xmit,
+	.xmit_async = at86rf230_xmit,
 	.ed = at86rf230_ed,
 	.set_channel = at86rf230_channel,
 	.start = at86rf230_start,
@@ -1541,7 +1534,6 @@ static int at86rf230_probe(struct spi_device *spi)
 		goto free_dev;
 
 	spin_lock_init(&lp->lock);
-	init_completion(&lp->tx_complete);
 	init_completion(&lp->state_complete);
 
 	spi_set_drvdata(spi, lp);
Signature · 1 line
2.1.2
#16 lore raw
In reply to Alexander Aring

Hi Alex,

Quoted 42 lines

This series contains patches for reworking tx handling. Also add a workaround to hold the xmit context when sending frames. Additional add support for asynchronous xmit handling and change the at86rf230 to do a asynchronous xmit handling.

Moving functions and renaming are necessary for the mac80211 naming convention.

changes since v2:
- remove whitespace in PATCH 14/15 ("mac802154: tx: add comment at sync xmit callback")

Alexander Aring (15):
mac802154: tx: move xmit callback to tx file
mac802154: tx: remove kmalloc in xmit hotpath
mac802154: tx: squash multiple dereferencing
mac802154: tx: remove xmit channel context switch
mac802154: add netdev qeue helpers
mac802154: tx: use queue helpers in xmit worker
mac802154: tx: fix error handling while xmit
mac802154: tx: add support for xmit_async callback
mac802154: tx: don't allow if down while sync tx
mac802154: tx: use netdev print helpers
mac802154: tx: cleanup crc calculation
mac802154: tx: move stats tx increment
mac802154: tx: change naming convention
mac802154: tx: add comment at sync xmit callback
at86rf230: asynchronous xmit handling

drivers/net/ieee802154/at86rf230.c |  42 +++++------
drivers/net/ieee802154/cc2520.c    |   2 +-
drivers/net/ieee802154/fakelb.c    |   2 +-
drivers/net/ieee802154/mrf24j40.c  |   2 +-
include/net/mac802154.h            |  28 +++++--
net/mac802154/Makefile             |   2 +-
net/mac802154/ieee802154_i.h       |   7 +-
net/mac802154/iface.c              |  37 +---------
net/mac802154/main.c               |   4 +-
net/mac802154/monitor.c            |  29 +-------
net/mac802154/tx.c                 | 145 ++++++++++++++++++++++---------------
net/mac802154/util.c               |  55 ++++++++++++++
12 files changed, 193 insertions(+), 162 deletions(-)
Quoted 1 line

create mode 100644 net/mac802154/util.c

all 15 patches have been applied to bluetooth-next tree.

Regards

Marcel