net: mac802154: Add a warning in the hot path

We should never start a transmission after the queue has been stopped.

But because it might work we don't kill the function here but rather
warn loudly the user that something is wrong.

Set a flag when the queue should remain stopped. Reset this flag when
the queue actually gets restarded. Just check this value to know if a
transmission is legitimate, warn if it is not.

Turn the flags variable into an unsigned long to allow the use of atomic
helpers on it.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Acked-by: Alexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/r/20220519150516.443078-11-miquel.raynal@bootlin.com
Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
This commit is contained in:
Miquel Raynal 2022-05-19 17:05:15 +02:00 committed by Stefan Schmidt
parent ddd9ee7cda
commit 2b13db13af
3 changed files with 21 additions and 3 deletions

View File

@ -166,11 +166,14 @@ wpan_phy_cca_cmp(const struct wpan_phy_cca *a, const struct wpan_phy_cca *b)
* level setting.
* @WPAN_PHY_FLAG_CCA_MODE: Indicates that transceiver will support cca mode
* setting.
* @WPAN_PHY_FLAG_STATE_QUEUE_STOPPED: Indicates that the transmit queue was
* temporarily stopped.
*/
enum wpan_phy_flags {
WPAN_PHY_FLAG_TXPOWER = BIT(1),
WPAN_PHY_FLAG_CCA_ED_LEVEL = BIT(2),
WPAN_PHY_FLAG_CCA_MODE = BIT(3),
WPAN_PHY_FLAG_STATE_QUEUE_STOPPED = BIT(4),
};
struct wpan_phy {
@ -182,7 +185,7 @@ struct wpan_phy {
*/
const void *privid;
u32 flags;
unsigned long flags;
/*
* This is a PIB according to 802.15.4-2011.

View File

@ -123,9 +123,13 @@ static int ieee802154_sync_queue(struct ieee802154_local *local)
int ieee802154_sync_and_hold_queue(struct ieee802154_local *local)
{
ieee802154_hold_queue(local);
int ret;
return ieee802154_sync_queue(local);
ieee802154_hold_queue(local);
ret = ieee802154_sync_queue(local);
set_bit(WPAN_PHY_FLAG_STATE_QUEUE_STOPPED, &local->phy->flags);
return ret;
}
int ieee802154_mlme_op_pre(struct ieee802154_local *local)
@ -172,9 +176,19 @@ int ieee802154_mlme_tx_one(struct ieee802154_local *local, struct sk_buff *skb)
return ret;
}
static bool ieee802154_queue_is_stopped(struct ieee802154_local *local)
{
return test_bit(WPAN_PHY_FLAG_STATE_QUEUE_STOPPED, &local->phy->flags);
}
static netdev_tx_t
ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
{
/* Warn if the net interface tries to transmit frames while the
* ieee802154 core assumes the queue is stopped.
*/
WARN_ON_ONCE(ieee802154_queue_is_stopped(local));
return ieee802154_tx(local, skb);
}

View File

@ -29,6 +29,7 @@ static void ieee802154_wake_queue(struct ieee802154_hw *hw)
struct ieee802154_sub_if_data *sdata;
rcu_read_lock();
clear_bit(WPAN_PHY_FLAG_STATE_QUEUE_STOPPED, &local->phy->flags);
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!sdata->dev)
continue;