diff options
author | Alexander Aring <alex.aring@gmail.com> | 2015-05-17 15:45:05 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-05-19 05:44:46 -0400 |
commit | e369dc8f1aa95cd490e1ab75043dcf50d2190453 (patch) | |
tree | 4e6693168f9ffa162fe1c4566750ef20ac9f7962 /drivers/net/ieee802154 | |
parent | 6fa2cffe8cf937fc10be362a2dcac8a5965f618e (diff) |
fakelb: introduce fakelb ifup phys list
This patch introduce a fakelb ifup phys list, which stores all
registered phys which are in an operated mode. This will reduce the
iterations of non-operated phys while transmit frames. There exists two
locks now, one rwlock for the operated interfaces and the spinlock for
protecting the list for all registered virtual phys.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/net/ieee802154')
-rw-r--r-- | drivers/net/ieee802154/fakelb.c | 58 |
1 files changed, 25 insertions, 33 deletions
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c index e1c0195c18aa..83957de47243 100644 --- a/drivers/net/ieee802154/fakelb.c +++ b/drivers/net/ieee802154/fakelb.c | |||
@@ -28,16 +28,18 @@ | |||
28 | #include <net/cfg802154.h> | 28 | #include <net/cfg802154.h> |
29 | 29 | ||
30 | static int numlbs = 2; | 30 | static int numlbs = 2; |
31 | static DEFINE_RWLOCK(fakelb_lock); | 31 | |
32 | static LIST_HEAD(fakelb_phys); | 32 | static LIST_HEAD(fakelb_phys); |
33 | static DEFINE_SPINLOCK(fakelb_phys_lock); | ||
34 | |||
35 | static LIST_HEAD(fakelb_ifup_phys); | ||
36 | static DEFINE_RWLOCK(fakelb_ifup_phys_lock); | ||
33 | 37 | ||
34 | struct fakelb_phy { | 38 | struct fakelb_phy { |
35 | struct ieee802154_hw *hw; | 39 | struct ieee802154_hw *hw; |
36 | 40 | ||
37 | struct list_head list; | 41 | struct list_head list; |
38 | 42 | struct list_head list_ifup; | |
39 | spinlock_t lock; | ||
40 | bool working; | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | static int | 45 | static int |
@@ -62,13 +64,9 @@ fakelb_hw_deliver(struct fakelb_phy *phy, struct sk_buff *skb) | |||
62 | { | 64 | { |
63 | struct sk_buff *newskb; | 65 | struct sk_buff *newskb; |
64 | 66 | ||
65 | spin_lock(&phy->lock); | 67 | newskb = pskb_copy(skb, GFP_ATOMIC); |
66 | if (phy->working) { | 68 | if (newskb) |
67 | newskb = pskb_copy(skb, GFP_ATOMIC); | 69 | ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc); |
68 | if (newskb) | ||
69 | ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc); | ||
70 | } | ||
71 | spin_unlock(&phy->lock); | ||
72 | } | 70 | } |
73 | 71 | ||
74 | static int | 72 | static int |
@@ -77,8 +75,8 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) | |||
77 | struct fakelb_phy *current_phy = hw->priv; | 75 | struct fakelb_phy *current_phy = hw->priv; |
78 | struct fakelb_phy *phy; | 76 | struct fakelb_phy *phy; |
79 | 77 | ||
80 | read_lock_bh(&fakelb_lock); | 78 | read_lock_bh(&fakelb_ifup_phys_lock); |
81 | list_for_each_entry(phy, &fakelb_phys, list) { | 79 | list_for_each_entry(phy, &fakelb_ifup_phys, list_ifup) { |
82 | if (current_phy == phy) | 80 | if (current_phy == phy) |
83 | continue; | 81 | continue; |
84 | 82 | ||
@@ -86,7 +84,7 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) | |||
86 | current_phy->hw->phy->current_channel) | 84 | current_phy->hw->phy->current_channel) |
87 | fakelb_hw_deliver(phy, skb); | 85 | fakelb_hw_deliver(phy, skb); |
88 | } | 86 | } |
89 | read_unlock_bh(&fakelb_lock); | 87 | read_unlock_bh(&fakelb_ifup_phys_lock); |
90 | 88 | ||
91 | return 0; | 89 | return 0; |
92 | } | 90 | } |
@@ -94,25 +92,21 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) | |||
94 | static int | 92 | static int |
95 | fakelb_hw_start(struct ieee802154_hw *hw) { | 93 | fakelb_hw_start(struct ieee802154_hw *hw) { |
96 | struct fakelb_phy *phy = hw->priv; | 94 | struct fakelb_phy *phy = hw->priv; |
97 | int ret = 0; | ||
98 | 95 | ||
99 | spin_lock(&phy->lock); | 96 | write_lock_bh(&fakelb_ifup_phys_lock); |
100 | if (phy->working) | 97 | list_add(&phy->list_ifup, &fakelb_ifup_phys); |
101 | ret = -EBUSY; | 98 | write_unlock_bh(&fakelb_ifup_phys_lock); |
102 | else | ||
103 | phy->working = 1; | ||
104 | spin_unlock(&phy->lock); | ||
105 | 99 | ||
106 | return ret; | 100 | return 0; |
107 | } | 101 | } |
108 | 102 | ||
109 | static void | 103 | static void |
110 | fakelb_hw_stop(struct ieee802154_hw *hw) { | 104 | fakelb_hw_stop(struct ieee802154_hw *hw) { |
111 | struct fakelb_phy *phy = hw->priv; | 105 | struct fakelb_phy *phy = hw->priv; |
112 | 106 | ||
113 | spin_lock(&phy->lock); | 107 | write_lock_bh(&fakelb_ifup_phys_lock); |
114 | phy->working = 0; | 108 | list_del(&phy->list_ifup); |
115 | spin_unlock(&phy->lock); | 109 | write_unlock_bh(&fakelb_ifup_phys_lock); |
116 | } | 110 | } |
117 | 111 | ||
118 | static const struct ieee802154_ops fakelb_ops = { | 112 | static const struct ieee802154_ops fakelb_ops = { |
@@ -172,17 +166,15 @@ static int fakelb_add_one(struct device *dev) | |||
172 | /* 950 MHz GFSK 802.15.4d-2009 */ | 166 | /* 950 MHz GFSK 802.15.4d-2009 */ |
173 | hw->phy->supported.channels[6] |= 0x3ffc00; | 167 | hw->phy->supported.channels[6] |= 0x3ffc00; |
174 | 168 | ||
175 | spin_lock_init(&phy->lock); | ||
176 | |||
177 | hw->parent = dev; | 169 | hw->parent = dev; |
178 | 170 | ||
179 | err = ieee802154_register_hw(hw); | 171 | err = ieee802154_register_hw(hw); |
180 | if (err) | 172 | if (err) |
181 | goto err_reg; | 173 | goto err_reg; |
182 | 174 | ||
183 | write_lock_bh(&fakelb_lock); | 175 | spin_lock(&fakelb_phys_lock); |
184 | list_add_tail(&phy->list, &fakelb_phys); | 176 | list_add_tail(&phy->list, &fakelb_phys); |
185 | write_unlock_bh(&fakelb_lock); | 177 | spin_unlock(&fakelb_phys_lock); |
186 | 178 | ||
187 | return 0; | 179 | return 0; |
188 | 180 | ||
@@ -215,10 +207,10 @@ static int fakelb_probe(struct platform_device *pdev) | |||
215 | return 0; | 207 | return 0; |
216 | 208 | ||
217 | err_slave: | 209 | err_slave: |
218 | write_lock_bh(&fakelb_lock); | 210 | spin_lock(&fakelb_phys_lock); |
219 | list_for_each_entry_safe(phy, tmp, &fakelb_phys, list) | 211 | list_for_each_entry_safe(phy, tmp, &fakelb_phys, list) |
220 | fakelb_del(phy); | 212 | fakelb_del(phy); |
221 | write_unlock_bh(&fakelb_lock); | 213 | spin_unlock(&fakelb_phys_lock); |
222 | return err; | 214 | return err; |
223 | } | 215 | } |
224 | 216 | ||
@@ -226,10 +218,10 @@ static int fakelb_remove(struct platform_device *pdev) | |||
226 | { | 218 | { |
227 | struct fakelb_phy *phy, *temp; | 219 | struct fakelb_phy *phy, *temp; |
228 | 220 | ||
229 | write_lock_bh(&fakelb_lock); | 221 | spin_lock(&fakelb_phys_lock); |
230 | list_for_each_entry_safe(phy, temp, &fakelb_phys, list) | 222 | list_for_each_entry_safe(phy, temp, &fakelb_phys, list) |
231 | fakelb_del(phy); | 223 | fakelb_del(phy); |
232 | write_unlock_bh(&fakelb_lock); | 224 | spin_unlock(&fakelb_phys_lock); |
233 | return 0; | 225 | return 0; |
234 | } | 226 | } |
235 | 227 | ||