diff options
author | Alexander Aring <alex.aring@gmail.com> | 2014-10-26 04:37:09 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-10-26 12:24:04 -0400 |
commit | 6001d5223dd458e4f0063df2a24762eb2a619b17 (patch) | |
tree | 0a5f40246fa30dc7b87eec2b78baa59b1c229dc8 /net/mac802154 | |
parent | ed0a5dce0c29f30ee53a87793206156cf38ae70d (diff) |
mac802154: tx: don't allow if down while sync tx
This patch holds rtnl lock while sync xmit inside of workqueue.
Otherwise we could down the interface while worker xmit handling.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/mac802154')
-rw-r--r-- | net/mac802154/tx.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index 1a4f6d91ab8c..44390419af86 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/if_arp.h> | 21 | #include <linux/if_arp.h> |
22 | #include <linux/crc-ccitt.h> | 22 | #include <linux/crc-ccitt.h> |
23 | 23 | ||
24 | #include <net/rtnetlink.h> | ||
24 | #include <net/ieee802154_netdev.h> | 25 | #include <net/ieee802154_netdev.h> |
25 | #include <net/mac802154.h> | 26 | #include <net/mac802154.h> |
26 | #include <net/cfg802154.h> | 27 | #include <net/cfg802154.h> |
@@ -50,16 +51,28 @@ static void mac802154_xmit_worker(struct work_struct *work) | |||
50 | struct sk_buff *skb = cb->skb; | 51 | struct sk_buff *skb = cb->skb; |
51 | int res; | 52 | int res; |
52 | 53 | ||
54 | rtnl_lock(); | ||
55 | |||
56 | /* check if ifdown occurred while schedule */ | ||
57 | if (!netif_running(skb->dev)) | ||
58 | goto err_tx; | ||
59 | |||
53 | res = local->ops->xmit_sync(&local->hw, skb); | 60 | res = local->ops->xmit_sync(&local->hw, skb); |
54 | if (res) { | 61 | if (res) |
55 | pr_debug("transmission failed\n"); | 62 | goto err_tx; |
56 | /* Restart the netif queue on each sub_if_data object. */ | 63 | |
57 | ieee802154_wake_queue(&local->hw); | 64 | ieee802154_xmit_complete(&local->hw, skb); |
58 | kfree_skb(skb); | 65 | |
59 | } else { | 66 | rtnl_unlock(); |
60 | /* Restart the netif queue on each sub_if_data object. */ | 67 | |
61 | ieee802154_xmit_complete(&local->hw, skb); | 68 | return; |
62 | } | 69 | |
70 | err_tx: | ||
71 | /* Restart the netif queue on each sub_if_data object. */ | ||
72 | ieee802154_wake_queue(&local->hw); | ||
73 | rtnl_unlock(); | ||
74 | kfree_skb(skb); | ||
75 | pr_debug("transmission failed\n"); | ||
63 | } | 76 | } |
64 | 77 | ||
65 | static netdev_tx_t | 78 | static netdev_tx_t |