Commit ed0a5dce authored by Alexander Aring's avatar Alexander Aring Committed by Marcel Holtmann

mac802154: tx: add support for xmit_async callback

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.
Signed-off-by: default avatarAlexander Aring <alex.aring@gmail.com>
Cc: Alan Ott <alan@signal11.us>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent cdb66bea
...@@ -1237,7 +1237,7 @@ at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries) ...@@ -1237,7 +1237,7 @@ at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
static struct ieee802154_ops at86rf230_ops = { static struct ieee802154_ops at86rf230_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.xmit = at86rf230_xmit, .xmit_sync = at86rf230_xmit,
.ed = at86rf230_ed, .ed = at86rf230_ed,
.set_channel = at86rf230_channel, .set_channel = at86rf230_channel,
.start = at86rf230_start, .start = at86rf230_start,
......
...@@ -635,7 +635,7 @@ static struct ieee802154_ops cc2520_ops = { ...@@ -635,7 +635,7 @@ static struct ieee802154_ops cc2520_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.start = cc2520_start, .start = cc2520_start,
.stop = cc2520_stop, .stop = cc2520_stop,
.xmit = cc2520_tx, .xmit_sync = cc2520_tx,
.ed = cc2520_ed, .ed = cc2520_ed,
.set_channel = cc2520_set_channel, .set_channel = cc2520_set_channel,
.set_hw_addr_filt = cc2520_filter, .set_hw_addr_filt = cc2520_filter,
......
...@@ -131,7 +131,7 @@ fakelb_hw_stop(struct ieee802154_hw *hw) { ...@@ -131,7 +131,7 @@ fakelb_hw_stop(struct ieee802154_hw *hw) {
static struct ieee802154_ops fakelb_ops = { static struct ieee802154_ops fakelb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.xmit = fakelb_hw_xmit, .xmit_sync = fakelb_hw_xmit,
.ed = fakelb_hw_ed, .ed = fakelb_hw_ed,
.set_channel = fakelb_hw_channel, .set_channel = fakelb_hw_channel,
.start = fakelb_hw_start, .start = fakelb_hw_start,
......
...@@ -581,7 +581,7 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec) ...@@ -581,7 +581,7 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
static struct ieee802154_ops mrf24j40_ops = { static struct ieee802154_ops mrf24j40_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.xmit = mrf24j40_tx, .xmit_sync = mrf24j40_tx,
.ed = mrf24j40_ed, .ed = mrf24j40_ed,
.start = mrf24j40_start, .start = mrf24j40_start,
.stop = mrf24j40_stop, .stop = mrf24j40_stop,
......
...@@ -109,7 +109,16 @@ struct ieee802154_hw { ...@@ -109,7 +109,16 @@ struct ieee802154_hw {
* stop: Handler that 802.15.4 module calls for device cleanup. * stop: Handler that 802.15.4 module calls for device cleanup.
* This function is called after the last interface is removed. * 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. * skb cntains the buffer starting from the IEEE 802.15.4 header.
* The low-level driver should send the frame based on available * The low-level driver should send the frame based on available
* configuration. * configuration.
...@@ -160,7 +169,9 @@ struct ieee802154_ops { ...@@ -160,7 +169,9 @@ struct ieee802154_ops {
struct module *owner; struct module *owner;
int (*start)(struct ieee802154_hw *hw); int (*start)(struct ieee802154_hw *hw);
void (*stop)(struct ieee802154_hw *hw); void (*stop)(struct ieee802154_hw *hw);
int (*xmit)(struct ieee802154_hw *hw, int (*xmit_sync)(struct ieee802154_hw *hw,
struct sk_buff *skb);
int (*xmit_async)(struct ieee802154_hw *hw,
struct sk_buff *skb); struct sk_buff *skb);
int (*ed)(struct ieee802154_hw *hw, u8 *level); int (*ed)(struct ieee802154_hw *hw, u8 *level);
int (*set_channel)(struct ieee802154_hw *hw, int (*set_channel)(struct ieee802154_hw *hw,
......
...@@ -229,8 +229,8 @@ ieee802154_alloc_hw(size_t priv_data_len, struct ieee802154_ops *ops) ...@@ -229,8 +229,8 @@ ieee802154_alloc_hw(size_t priv_data_len, struct ieee802154_ops *ops)
struct ieee802154_local *local; struct ieee802154_local *local;
size_t priv_size; size_t priv_size;
if (!ops || !ops->xmit || !ops->ed || !ops->start || if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed ||
!ops->stop || !ops->set_channel) { !ops->start || !ops->stop || !ops->set_channel) {
pr_err("undefined IEEE802.15.4 device operations\n"); pr_err("undefined IEEE802.15.4 device operations\n");
return NULL; return NULL;
} }
......
...@@ -50,7 +50,7 @@ static void mac802154_xmit_worker(struct work_struct *work) ...@@ -50,7 +50,7 @@ static void mac802154_xmit_worker(struct work_struct *work)
struct sk_buff *skb = cb->skb; struct sk_buff *skb = cb->skb;
int res; int res;
res = local->ops->xmit(&local->hw, skb); res = local->ops->xmit_sync(&local->hw, skb);
if (res) { if (res) {
pr_debug("transmission failed\n"); pr_debug("transmission failed\n");
/* Restart the netif queue on each sub_if_data object. */ /* Restart the netif queue on each sub_if_data object. */
...@@ -66,6 +66,7 @@ static netdev_tx_t ...@@ -66,6 +66,7 @@ static netdev_tx_t
mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb) mac802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
{ {
struct wpan_xmit_cb *cb = wpan_xmit_cb(skb); struct wpan_xmit_cb *cb = wpan_xmit_cb(skb);
int ret;
mac802154_monitors_rx(local, skb); mac802154_monitors_rx(local, skb);
...@@ -83,11 +84,20 @@ mac802154_tx(struct ieee802154_local *local, struct sk_buff *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. */ /* Stop the netif queue on each sub_if_data object. */
ieee802154_stop_queue(&local->hw); ieee802154_stop_queue(&local->hw);
/* 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); INIT_WORK(&cb->work, mac802154_xmit_worker);
cb->skb = skb; cb->skb = skb;
cb->local = local; cb->local = local;
queue_work(local->workqueue, &cb->work); queue_work(local->workqueue, &cb->work);
}
return NETDEV_TX_OK; return NETDEV_TX_OK;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment