Commit 2b13db13 authored by Miquel Raynal's avatar Miquel Raynal Committed by Stefan Schmidt
Browse files

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: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Acked-by: default avatarAlexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/r/20220519150516.443078-11-miquel.raynal@bootlin.com


Signed-off-by: default avatarStefan Schmidt <stefan@datenfreihafen.org>
parent ddd9ee7c
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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.
+15 −1
Original line number Diff line number Diff line
@@ -123,9 +123,13 @@ static int ieee802154_sync_queue(struct ieee802154_local *local)

int ieee802154_sync_and_hold_queue(struct ieee802154_local *local)
{
	int ret;

	ieee802154_hold_queue(local);
	ret = ieee802154_sync_queue(local);
	set_bit(WPAN_PHY_FLAG_STATE_QUEUE_STOPPED, &local->phy->flags);

	return ieee802154_sync_queue(local);
	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);
}

+1 −0
Original line number Diff line number Diff line
@@ -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;