Skip to content

Commit

Permalink
mac802154: cfg: add suspend and resume callbacks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
alexaring authored and holtmann committed Jul 23, 2015
1 parent a6cb869 commit 3cf24cf
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 2 deletions.
45 changes: 45 additions & 0 deletions net/mac802154/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,49 @@ static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
ieee802154_if_remove(sdata);
}

#ifdef CONFIG_PM
static int ieee802154_suspend(struct wpan_phy *wpan_phy)
{
struct ieee802154_local *local = wpan_phy_priv(wpan_phy);

if (!local->open_count)
goto suspend;

ieee802154_stop_queue(&local->hw);
synchronize_net();

/* stop hardware - this must stop RX */
ieee802154_stop_device(local);

suspend:
local->suspended = true;
return 0;
}

static int ieee802154_resume(struct wpan_phy *wpan_phy)
{
struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
int ret;

/* nothing to do if HW shouldn't run */
if (!local->open_count)
goto wake_up;

/* restart hardware */
ret = drv_start(local);
if (ret)
return ret;

wake_up:
ieee802154_wake_queue(&local->hw);
local->suspended = false;
return 0;
}
#else
#define ieee802154_suspend NULL
#define ieee802154_resume NULL
#endif

static int
ieee802154_add_iface(struct wpan_phy *phy, const char *name,
unsigned char name_assign_type,
Expand Down Expand Up @@ -232,6 +275,8 @@ ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
const struct cfg802154_ops mac802154_config_ops = {
.add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
.del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
.suspend = ieee802154_suspend,
.resume = ieee802154_resume,
.add_virtual_intf = ieee802154_add_iface,
.del_virtual_intf = ieee802154_del_iface,
.set_channel = ieee802154_set_channel,
Expand Down
1 change: 1 addition & 0 deletions net/mac802154/ieee802154_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct ieee802154_local {
struct hrtimer ifs_timer;

bool started;
bool suspended;

struct tasklet_struct tasklet;
struct sk_buff_head skb_queue;
Expand Down
10 changes: 8 additions & 2 deletions net/mac802154/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)

WARN_ON_ONCE(softirq_count() == 0);

if (local->suspended)
goto drop;

/* TODO: When a transceiver omits the checksum here, we
* add an own calculated one. This is currently an ugly
* solution because the monitor needs a crc here.
Expand All @@ -273,8 +276,7 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
crc = crc_ccitt(0, skb->data, skb->len);
if (crc) {
rcu_read_unlock();
kfree_skb(skb);
return;
goto drop;
}
}
/* remove crc */
Expand All @@ -283,6 +285,10 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
__ieee802154_rx_handle_packet(local, skb);

rcu_read_unlock();

return;
drop:
kfree_skb(skb);
}
EXPORT_SYMBOL(ieee802154_rx);

Expand Down

0 comments on commit 3cf24cf

Please sign in to comment.