aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2015-06-24 05:36:36 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-07-23 11:10:49 -0400
commit3cf24cf8c3c06f9a6cacc8fc2cad94661b6096b6 (patch)
treeb1192515ba1dcac09a108816386df1145a003a7c
parenta6cb869b3b7c16fd7c3ee766dd9f9a4fdda7edf9 (diff)
mac802154: cfg: add suspend and resume callbacks
This patch introduces suspend and resume callbacks to mac802154. When doing suspend we calling the stop driver callback which should stop the receiving of frames. A transceiver should go into low-power mode then. Calling resume will call the start driver callback, which starts receiving again and allow to transmit frames. This was tested only with the fakelb driver and a qemu vm by doing the following commands: echo "devices" > /sys/power/pm_test echo "freeze" > /sys/power/state while doing some high traffic between two fakelb phys. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--net/mac802154/cfg.c45
-rw-r--r--net/mac802154/ieee802154_i.h1
-rw-r--r--net/mac802154/rx.c10
3 files changed, 54 insertions, 2 deletions
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 44db8613812e..f7ba51e8b4ca 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -44,6 +44,49 @@ static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
44 ieee802154_if_remove(sdata); 44 ieee802154_if_remove(sdata);
45} 45}
46 46
47#ifdef CONFIG_PM
48static int ieee802154_suspend(struct wpan_phy *wpan_phy)
49{
50 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
51
52 if (!local->open_count)
53 goto suspend;
54
55 ieee802154_stop_queue(&local->hw);
56 synchronize_net();
57
58 /* stop hardware - this must stop RX */
59 ieee802154_stop_device(local);
60
61suspend:
62 local->suspended = true;
63 return 0;
64}
65
66static int ieee802154_resume(struct wpan_phy *wpan_phy)
67{
68 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
69 int ret;
70
71 /* nothing to do if HW shouldn't run */
72 if (!local->open_count)
73 goto wake_up;
74
75 /* restart hardware */
76 ret = drv_start(local);
77 if (ret)
78 return ret;
79
80wake_up:
81 ieee802154_wake_queue(&local->hw);
82 local->suspended = false;
83 return 0;
84}
85#else
86#define ieee802154_suspend NULL
87#define ieee802154_resume NULL
88#endif
89
47static int 90static int
48ieee802154_add_iface(struct wpan_phy *phy, const char *name, 91ieee802154_add_iface(struct wpan_phy *phy, const char *name,
49 unsigned char name_assign_type, 92 unsigned char name_assign_type,
@@ -232,6 +275,8 @@ ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
232const struct cfg802154_ops mac802154_config_ops = { 275const struct cfg802154_ops mac802154_config_ops = {
233 .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, 276 .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
234 .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, 277 .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
278 .suspend = ieee802154_suspend,
279 .resume = ieee802154_resume,
235 .add_virtual_intf = ieee802154_add_iface, 280 .add_virtual_intf = ieee802154_add_iface,
236 .del_virtual_intf = ieee802154_del_iface, 281 .del_virtual_intf = ieee802154_del_iface,
237 .set_channel = ieee802154_set_channel, 282 .set_channel = ieee802154_set_channel,
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 04077830e88c..0054f39d499b 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -56,6 +56,7 @@ struct ieee802154_local {
56 struct hrtimer ifs_timer; 56 struct hrtimer ifs_timer;
57 57
58 bool started; 58 bool started;
59 bool suspended;
59 60
60 struct tasklet_struct tasklet; 61 struct tasklet_struct tasklet;
61 struct sk_buff_head skb_queue; 62 struct sk_buff_head skb_queue;
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index d93ad2d4a4fc..5a258c11ed3b 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -253,6 +253,9 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
253 253
254 WARN_ON_ONCE(softirq_count() == 0); 254 WARN_ON_ONCE(softirq_count() == 0);
255 255
256 if (local->suspended)
257 goto drop;
258
256 /* TODO: When a transceiver omits the checksum here, we 259 /* TODO: When a transceiver omits the checksum here, we
257 * add an own calculated one. This is currently an ugly 260 * add an own calculated one. This is currently an ugly
258 * solution because the monitor needs a crc here. 261 * solution because the monitor needs a crc here.
@@ -273,8 +276,7 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
273 crc = crc_ccitt(0, skb->data, skb->len); 276 crc = crc_ccitt(0, skb->data, skb->len);
274 if (crc) { 277 if (crc) {
275 rcu_read_unlock(); 278 rcu_read_unlock();
276 kfree_skb(skb); 279 goto drop;
277 return;
278 } 280 }
279 } 281 }
280 /* remove crc */ 282 /* remove crc */
@@ -283,6 +285,10 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
283 __ieee802154_rx_handle_packet(local, skb); 285 __ieee802154_rx_handle_packet(local, skb);
284 286
285 rcu_read_unlock(); 287 rcu_read_unlock();
288
289 return;
290drop:
291 kfree_skb(skb);
286} 292}
287EXPORT_SYMBOL(ieee802154_rx); 293EXPORT_SYMBOL(ieee802154_rx);
288 294