summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ieee802154/at86rf230.c2
-rw-r--r--drivers/net/ieee802154/cc2520.c2
-rw-r--r--drivers/net/ieee802154/fakelb.c2
-rw-r--r--drivers/net/ieee802154/mrf24j40.c2
-rw-r--r--include/net/mac802154.h17
-rw-r--r--net/mac802154/main.c4
-rw-r--r--net/mac802154/tx.c20
7 files changed, 35 insertions, 14 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index b0d68d7061c1..06a3e9013d60 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -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,
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
index b827e04d481b..f6f07f4eb0ec 100644
--- a/drivers/net/ieee802154/cc2520.c
+++ b/drivers/net/ieee802154/cc2520.c
@@ -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,
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index 51e3c589d2e4..db0703f0fa41 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -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,
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 2e267c5c44da..3d775afa217f 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -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,
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 29af5c346ebf..57b120281afc 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -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,
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 0e9a6a203f7a..3c0a824d24ac 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -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;
}
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 23139cae0764..1a4f6d91ab8c 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -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;