linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/41] IEEE 802.15.4 scan support
@ 2022-01-17 11:53 Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 01/41] MAINTAINERS: Remove Harry Morris bouncing address Miquel Raynal
                   ` (41 more replies)
  0 siblings, 42 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:53 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Hello,

	*** TLDR ***

Here is a series attempting to bring support for scans in the
IEEE 802.15.4 stack. A number of improvements had to be made, including:
* a better handling of the symbol durations
* a few changes in Kconfig
* a better handling of the tx queues
* a synchronous Tx API

Active and passive scans can be locally tested only with hwsim.

Sorry for the big series, might be split in the near future.

	************

A second series aligning the tooling with these changes is related,
bringing support for a number of new features such as:

* Sending (or stopping) beacons. Intervals ranging from 0 to 14 are
  valid for passively sending beacons at regular intervals. An interval
  of 15 would request the core to answer to received BEACON_REQ.
  # iwpan dev wpan0 beacons send interval 2 # send BEACON at a fixed rate
  # iwpan dev wpan0 beacons send interval 15 # answer BEACON_REQ only
  # iwpan dev wpan0 beacons stop # apply to both cases

* Scanning all the channels or only a subset:
  # iwpan dev wpan1 scan type passive duration 3 # will not trigger BEACON_REQ
  # iwpan dev wpan1 scan type active duration 3 # will trigger BEACON_REQ

* If a beacon is received during a scan, the internal PAN list is
  updated and can be dumped, flushed and configured with:
  # iwpan dev wpan1 pans dump
  PAN 0xffff (on wpan1)
      coordinator 0x2efefdd4cdbf9330
      page 0
      channel 13
      superframe spec. 0xcf22
      LQI 0
      seen 7156ms ago
  # iwpan dev wpan1 pans flush
  # iwpan dev wpan1 set max_pan_entries 100
  # iwpan dev wpan1 set pans_expiration 3600

* It is also possible to monitor the events with:
  # iwpan event

* As well as triggering a non blocking scan:
  # iwpan dev wpan1 scan trigger type passive duration 3
  # iwpan dev wpan1 scan done
  # iwpan dev wpan1 scan abort

The PAN list gets automatically updated by dropping the expired PANs
each time the user requests access to the list.

Internally, both requests (scan/beacons) are handled periodically by
delayed workqueues when relevant.

So far the only technical point that is missing in this series is the
possibility to grab a reference over the module driving the net device
in order to prevent module unloading during a scan or when the beacons
work is ongoing.

Finally, this series is a deep reshuffle of David Girault's original
work, hence the fact that he is almost systematically credited, either
by being the only author when I created the patches based on his changes
with almost no modification, or with a Co-developped-by tag whenever the
final code base is significantly different than his first proposal while
still being greatly inspired from it.

Cheers,
Miquèl

Changes in v3:
* Dropped two patches:
  net: mac802154: Split the set channel hook implementation
  net: mac802154: Ensure proper channel selection at probe time
* Fixed a check against the supported channels list in
  ieee802154_set_symbol_duration().
* Reworded a bit the above helper to print different error messages and
  dropped the goto statement in it.
* Used the NSEC_PER_USEC macro in the symbol conversion from us to ns.
* Stopped calling ->set_channel() at probe time.
* Fixed hwsim which does not internally set the right channel.
* Used definitions instead of hardcoded values when relevant.
* Moved two helpers out of the experimental section because they are now
  used outside of experimental code.
* Did a number of renames. Added a couple of comments.
* Updated several drivers to force them to use the core xmit complete
  callback instead of workarounding it.
* Created a helper checking if a queue must be kept on hold.
* Created a couple of atomic variables and wait_queue_t per phy.
* Created a sync API for MLME transmissions.
* Created a hot path and a slow path.
* Put the warning in the hot path.
* Added a flag to prevent drivers supporting only datagrams to use the
  different scanning features.
* Dropped ieee802154_wake/stop_queue() from the exported
  symbols. Drivers should not use these directly, but call other helpers
  in order to fail the tx counters.

Changes in v2:
* Create two new netlink commands to set the maximum number of PANs that
  can be listed as well as their expiration time (in seconds).
* Added a patch to the series to avoid ignoring bad frames in hwsim as
  requested by Alexander.
* Changed the symbol duration type to receive nanoseconds instead of
  microseconds.
* Dropped most of the hwsim patches and reworked how drivers advertise
  their channels in order to be capable of deriving the symbol durations
  automatically.
* The scanning boolean gets turned into an atomic.
* The ca8210 driver does not support scanning, implement the driver
  hooks to reflect the situation.
* Reworked a bit the content of each patch to ease the introduction of
  active scans. 
* Added active scan support.

David Girault (5):
  net: ieee802154: Move IEEE 802.15.4 Kconfig main entry
  net: mac802154: Include the softMAC stack inside the IEEE 802.15.4
    menu
  net: ieee802154: Move the address structure earlier
  net: ieee802154: Add a kernel doc header to the ieee802154_addr
    structure
  net: ieee802154: Trace the registration of new PANs

Miquel Raynal (36):
  MAINTAINERS: Remove Harry Morris bouncing address
  net: ieee802154: hwsim: Ensure proper channel selection at probe time
  net: ieee802154: hwsim: Ensure frame checksum are valid
  net: ieee802154: Use the IEEE802154_MAX_PAGE define when relevant
  net: ieee802154: Improve the way supported channels are declared
  net: ieee802154: Give more details to the core about the channel
    configurations
  net: ieee802154: mcr20a: Fix lifs/sifs periods
  net: mac802154: Convert the symbol duration into nanoseconds
  net: mac802154: Set the symbol duration automatically
  net: ieee802154: Drop duration settings when the core does it already
  net: ieee802154: Return meaningful error codes from the netlink
    helpers
  net: mac802154: Explain the use of ieee802154_wake/stop_queue()
  net: ieee802154: at86rf230: Call the complete helper when a
    transmission is over
  net: ieee802154: atusb: Call the complete helper when a transmission
    is over
  net: ieee802154: ca8210: Call the complete helper when a transmission
    is over
  net: mac802154: Stop exporting ieee802154_wake/stop_queue()
  net: mac802154: Rename the synchronous xmit worker
  net: mac802154: Rename the main tx_work struct
  net: mac802154: Follow the count of ongoing transmissions
  net: mac802154: Hold the transmit queue when relevant
  net: mac802154: Create a hot tx path
  net: mac802154: Add a warning in the hot path
  net: mac802154: Introduce a tx queue flushing mechanism
  net: mac802154: Introduce a synchronous API for MLME commands
  net: ieee802154: Add support for internal PAN management
  net: ieee802154: Define a beacon frame header
  net: ieee802154: Define frame types
  net: ieee802154: Add support for scanning requests
  net: mac802154: Handle scan requests
  net: ieee802154: Full PAN management
  net: ieee802154: Add beacons support
  net: mac802154: Handle beacons requests
  net: mac802154: Add support for active scans
  net: mac802154: Add support for processing beacon requests
  net: ieee802154: Handle limited devices with only datagram support
  net: ieee802154: ca8210: Flag the driver as being limited

 MAINTAINERS                              |   3 +-
 drivers/net/ieee802154/adf7242.c         |   3 +-
 drivers/net/ieee802154/at86rf230.c       |  68 ++-
 drivers/net/ieee802154/atusb.c           |  89 ++--
 drivers/net/ieee802154/ca8210.c          |  17 +-
 drivers/net/ieee802154/cc2520.c          |   3 +-
 drivers/net/ieee802154/fakelb.c          |  43 +-
 drivers/net/ieee802154/mac802154_hwsim.c |  88 +++-
 drivers/net/ieee802154/mcr20a.c          |  11 +-
 drivers/net/ieee802154/mrf24j40.c        |   3 +-
 include/linux/ieee802154.h               |   7 +
 include/net/cfg802154.h                  | 175 ++++++-
 include/net/ieee802154_netdev.h          |  85 ++++
 include/net/mac802154.h                  |  29 +-
 include/net/nl802154.h                   |  99 ++++
 net/Kconfig                              |   3 +-
 net/ieee802154/Kconfig                   |   1 +
 net/ieee802154/Makefile                  |   2 +-
 net/ieee802154/core.c                    |   3 +
 net/ieee802154/core.h                    |  31 ++
 net/ieee802154/header_ops.c              |  67 +++
 net/ieee802154/nl-phy.c                  |  13 +-
 net/ieee802154/nl802154.c                | 556 ++++++++++++++++++++++-
 net/ieee802154/nl802154.h                |   4 +
 net/ieee802154/pan.c                     | 234 ++++++++++
 net/ieee802154/rdev-ops.h                |  52 +++
 net/ieee802154/trace.h                   |  86 ++++
 net/mac802154/Makefile                   |   2 +-
 net/mac802154/cfg.c                      |  82 +++-
 net/mac802154/ieee802154_i.h             |  86 +++-
 net/mac802154/main.c                     | 119 ++++-
 net/mac802154/rx.c                       |  34 +-
 net/mac802154/scan.c                     | 447 ++++++++++++++++++
 net/mac802154/tx.c                       |  48 +-
 net/mac802154/util.c                     |  38 +-
 35 files changed, 2413 insertions(+), 218 deletions(-)
 create mode 100644 net/ieee802154/pan.c
 create mode 100644 net/mac802154/scan.c

-- 
2.27.0


^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v3 01/41] MAINTAINERS: Remove Harry Morris bouncing address
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 02/41] net: ieee802154: hwsim: Ensure proper channel selection at probe time Miquel Raynal
                   ` (40 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Harry's e-mail address from Cascoda bounces, I have not found any
contributions from him since 2018 so let's drop the Maintainer entry
from the CA8210 driver and mark it Orphan.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 MAINTAINERS | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4d479b554361..ab2b32080b73 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4099,9 +4099,8 @@ N:	csky
 K:	csky
 
 CA8210 IEEE-802.15.4 RADIO DRIVER
-M:	Harry Morris <h.morris@cascoda.com>
 L:	linux-wpan@vger.kernel.org
-S:	Maintained
+S:	Orphan
 W:	https://github.com/Cascoda/ca8210-linux.git
 F:	Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
 F:	drivers/net/ieee802154/ca8210.c
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 02/41] net: ieee802154: hwsim: Ensure proper channel selection at probe time
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 01/41] MAINTAINERS: Remove Harry Morris bouncing address Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 03/41] net: ieee802154: hwsim: Ensure frame checksum are valid Miquel Raynal
                   ` (39 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Drivers are expected to set the PHY current_channel and current_page
according to their default state. The hwsim driver is advertising being
configured on channel 13 by default but that is not reflected in its own
internal pib structure. In order to ensure that this driver consider the
current channel as being 13 internally, we can call hwsim_hw_channel()
instead of creating an empty pib structure.

We assume here that kvfree_rcu(NULL) is a valid call.

Fixes: f25da51fdc38 ("ieee802154: hwsim: add replacement for fakelb")
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/mac802154_hwsim.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 8caa61ec718f..795f8eb5387b 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -732,7 +732,6 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 {
 	struct ieee802154_hw *hw;
 	struct hwsim_phy *phy;
-	struct hwsim_pib *pib;
 	int idx;
 	int err;
 
@@ -780,13 +779,8 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 
 	/* hwsim phy channel 13 as default */
 	hw->phy->current_channel = 13;
-	pib = kzalloc(sizeof(*pib), GFP_KERNEL);
-	if (!pib) {
-		err = -ENOMEM;
-		goto err_pib;
-	}
+	hwsim_hw_channel(hw, hw->phy->current_page, hw->phy->current_channel);
 
-	rcu_assign_pointer(phy->pib, pib);
 	phy->idx = idx;
 	INIT_LIST_HEAD(&phy->edges);
 
@@ -815,8 +809,6 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 err_subscribe:
 	ieee802154_unregister_hw(phy->hw);
 err_reg:
-	kfree(pib);
-err_pib:
 	ieee802154_free_hw(phy->hw);
 	return err;
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 03/41] net: ieee802154: hwsim: Ensure frame checksum are valid
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 01/41] MAINTAINERS: Remove Harry Morris bouncing address Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 02/41] net: ieee802154: hwsim: Ensure proper channel selection at probe time Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 04/41] net: ieee802154: Use the IEEE802154_MAX_PAGE define when relevant Miquel Raynal
                   ` (38 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

There is no point in accepting frames with a wrong or missing checksum,
at least not outside of a promiscuous setting. Set the right flag by
default in the hwsim driver to ensure checksums are not ignored.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/mac802154_hwsim.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 795f8eb5387b..5324d0eda223 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -784,7 +784,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 	phy->idx = idx;
 	INIT_LIST_HEAD(&phy->edges);
 
-	hw->flags = IEEE802154_HW_PROMISCUOUS;
+	hw->flags = IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_RX_DROP_BAD_CKSUM;
 	hw->parent = dev;
 
 	err = ieee802154_register_hw(hw);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 04/41] net: ieee802154: Use the IEEE802154_MAX_PAGE define when relevant
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (2 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 03/41] net: ieee802154: hwsim: Ensure frame checksum are valid Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 05/41] net: ieee802154: Improve the way supported channels are declared Miquel Raynal
                   ` (37 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This define already exist but is hardcoded in nl-phy.c. Use the
definition when relevant.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/ieee802154/nl-phy.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index dd5a45f8a78a..02f6a53d0faa 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -30,7 +30,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 {
 	void *hdr;
 	int i, pages = 0;
-	uint32_t *buf = kcalloc(32, sizeof(uint32_t), GFP_KERNEL);
+	uint32_t *buf = kcalloc(IEEE802154_MAX_PAGE + 1, sizeof(uint32_t),
+				GFP_KERNEL);
 
 	pr_debug("%s\n", __func__);
 
@@ -47,7 +48,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	    nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
 	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
 		goto nla_put_failure;
-	for (i = 0; i < 32; i++) {
+	for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
 		if (phy->supported.channels[i])
 			buf[pages++] = phy->supported.channels[i] | (i << 27);
 	}
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 05/41] net: ieee802154: Improve the way supported channels are declared
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (3 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 04/41] net: ieee802154: Use the IEEE802154_MAX_PAGE define when relevant Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 06/41] net: ieee802154: Give more details to the core about the channel configurations Miquel Raynal
                   ` (36 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

The idea here is to create a structure per set of channels so that we
can define much more than basic bitfields for these.

The structure is currently almost empty on purpose because this change
is supposed to be a mechanical update without additional information but
more details will be added in the following commits.

For each page, the core now has access to how many "chunks" of channels
are defined. Overall up to only 3 chunks have been defined so let's
hardcode this value to simplify a lot the handling. Then, for each
chunk, we define an independent bitfield of channels. As there are
several users of these bitfields, we also create the
cfg802154_get_supported_chans() helper to reconstruct the bitfield as it
was before when the only information that matters is identifying the
supported/unsupported channels.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/adf7242.c         |  3 +-
 drivers/net/ieee802154/at86rf230.c       | 12 ++++---
 drivers/net/ieee802154/atusb.c           | 12 ++++---
 drivers/net/ieee802154/ca8210.c          |  3 +-
 drivers/net/ieee802154/cc2520.c          |  3 +-
 drivers/net/ieee802154/fakelb.c          | 43 +++++++++++++++---------
 drivers/net/ieee802154/mac802154_hwsim.c | 43 +++++++++++++++---------
 drivers/net/ieee802154/mcr20a.c          |  3 +-
 drivers/net/ieee802154/mrf24j40.c        |  3 +-
 include/net/cfg802154.h                  | 13 +++++--
 net/ieee802154/core.h                    |  2 ++
 net/ieee802154/nl-phy.c                  |  8 +++--
 net/ieee802154/nl802154.c                | 30 +++++++++++++----
 13 files changed, 125 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c
index 7db9cbd0f5de..40c77a643b78 100644
--- a/drivers/net/ieee802154/adf7242.c
+++ b/drivers/net/ieee802154/adf7242.c
@@ -1211,7 +1211,8 @@ static int adf7242_probe(struct spi_device *spi)
 	hw->extra_tx_headroom = 0;
 
 	/* We support only 2.4 Ghz */
-	hw->phy->supported.channels[0] = 0x7FFF800;
+	hw->phy->supported.page[0].nchunks = 1;
+	hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
 
 	hw->flags = IEEE802154_HW_OMIT_CKSUM |
 		    IEEE802154_HW_CSMA_PARAMS |
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 7d67f41387f5..cdf5d2a4f763 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -1558,7 +1558,8 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 	case 3:
 		chip = "at86rf231";
 		lp->data = &at86rf231_data;
-		lp->hw->phy->supported.channels[0] = 0x7FFF800;
+		lp->hw->phy->supported.page[0].nchunks = 1;
+		lp->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
 		lp->hw->phy->current_channel = 11;
 		lp->hw->phy->symbol_duration = 16;
 		lp->hw->phy->supported.tx_powers = at86rf231_powers;
@@ -1570,8 +1571,10 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		chip = "at86rf212";
 		lp->data = &at86rf212_data;
 		lp->hw->flags |= IEEE802154_HW_LBT;
-		lp->hw->phy->supported.channels[0] = 0x00007FF;
-		lp->hw->phy->supported.channels[2] = 0x00007FF;
+		lp->hw->phy->supported.page[0].nchunks = 1;
+		lp->hw->phy->supported.page[0].chunk[0].channels = 0x00007FF;
+		lp->hw->phy->supported.page[2].nchunks = 1;
+		lp->hw->phy->supported.page[2].chunk[0].channels = 0x00007FF;
 		lp->hw->phy->current_channel = 5;
 		lp->hw->phy->symbol_duration = 25;
 		lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
@@ -1583,7 +1586,8 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 	case 11:
 		chip = "at86rf233";
 		lp->data = &at86rf233_data;
-		lp->hw->phy->supported.channels[0] = 0x7FFF800;
+		lp->hw->phy->supported.page[0].nchunks = 1;
+		lp->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
 		lp->hw->phy->current_channel = 13;
 		lp->hw->phy->symbol_duration = 16;
 		lp->hw->phy->supported.tx_powers = at86rf233_powers;
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 23ee0b14cbfa..38ebfacf2698 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -914,7 +914,8 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 	switch (part_num) {
 	case 2:
 		chip = "AT86RF230";
-		atusb->hw->phy->supported.channels[0] = 0x7FFF800;
+		atusb->hw->phy->supported.page[0].nchunks = 1;
+		atusb->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
 		atusb->hw->phy->symbol_duration = 16;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
@@ -924,7 +925,8 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		break;
 	case 3:
 		chip = "AT86RF231";
-		atusb->hw->phy->supported.channels[0] = 0x7FFF800;
+		atusb->hw->phy->supported.page[0].nchunks = 1;
+		atusb->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
 		atusb->hw->phy->symbol_duration = 16;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
@@ -935,8 +937,10 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 	case 7:
 		chip = "AT86RF212";
 		atusb->hw->flags |= IEEE802154_HW_LBT;
-		atusb->hw->phy->supported.channels[0] = 0x00007FF;
-		atusb->hw->phy->supported.channels[2] = 0x00007FF;
+		atusb->hw->phy->supported.page[0].nchunks = 1;
+		atusb->hw->phy->supported.page[0].chunk[0].channels = 0x00007FF;
+		atusb->hw->phy->supported.page[2].nchunks = 1;
+		atusb->hw->phy->supported.page[2].chunk[0].channels = 0x00007FF;
 		atusb->hw->phy->current_channel = 5;
 		atusb->hw->phy->symbol_duration = 25;
 		atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index ece6ff6049f6..1a667fceb8ba 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2962,7 +2962,8 @@ static const s32 ca8210_ed_levels[CA8210_MAX_ED_LEVELS] = {
 static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
 {
 	/* Support channels 11-26 */
-	ca8210_hw->phy->supported.channels[0] = CA8210_VALID_CHANNELS;
+	ca8210_hw->phy->supported.page[0].nchunks = 1;
+	ca8210_hw->phy->supported.page[0].chunk[0].channels = CA8210_VALID_CHANNELS;
 	ca8210_hw->phy->supported.tx_powers_size = CA8210_MAX_TX_POWERS;
 	ca8210_hw->phy->supported.tx_powers = ca8210_tx_powers;
 	ca8210_hw->phy->supported.cca_ed_levels_size = CA8210_MAX_ED_LEVELS;
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
index 89c046b204e0..587f050ef4e8 100644
--- a/drivers/net/ieee802154/cc2520.c
+++ b/drivers/net/ieee802154/cc2520.c
@@ -836,7 +836,8 @@ static int cc2520_register(struct cc2520_private *priv)
 	ieee802154_random_extended_addr(&priv->hw->phy->perm_extended_addr);
 
 	/* We do support only 2.4 Ghz */
-	priv->hw->phy->supported.channels[0] = 0x7FFF800;
+	priv->hw->phy->supported.page[0].nchunks = 1;
+	priv->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
 	priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
 			  IEEE802154_HW_PROMISCUOUS;
 
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index 523d13ee02bf..bc44d1f7551c 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -137,36 +137,49 @@ static int fakelb_add_one(struct device *dev)
 	phy = hw->priv;
 	phy->hw = hw;
 
+	hw->phy->supported.page[0].nchunks = 3;
 	/* 868 MHz BPSK	802.15.4-2003 */
-	hw->phy->supported.channels[0] |= 1;
+	hw->phy->supported.page[0].chunk[0].channels |= 1;
 	/* 915 MHz BPSK	802.15.4-2003 */
-	hw->phy->supported.channels[0] |= 0x7fe;
+	hw->phy->supported.page[0].chunk[1].channels |= 0x7fe;
 	/* 2.4 GHz O-QPSK 802.15.4-2003 */
-	hw->phy->supported.channels[0] |= 0x7FFF800;
+	hw->phy->supported.page[0].chunk[2].channels |= 0x7FFF800;
+
+	hw->phy->supported.page[1].nchunks = 2;
 	/* 868 MHz ASK 802.15.4-2006 */
-	hw->phy->supported.channels[1] |= 1;
+	hw->phy->supported.page[1].chunk[0].channels |= 1;
 	/* 915 MHz ASK 802.15.4-2006 */
-	hw->phy->supported.channels[1] |= 0x7fe;
+	hw->phy->supported.page[1].chunk[1].channels |= 0x7fe;
+
+	hw->phy->supported.page[2].nchunks = 2;
 	/* 868 MHz O-QPSK 802.15.4-2006 */
-	hw->phy->supported.channels[2] |= 1;
+	hw->phy->supported.page[2].chunk[0].channels |= 1;
 	/* 915 MHz O-QPSK 802.15.4-2006 */
-	hw->phy->supported.channels[2] |= 0x7fe;
+	hw->phy->supported.page[2].chunk[1].channels |= 0x7fe;
+
+	hw->phy->supported.page[3].nchunks = 1;
 	/* 2.4 GHz CSS 802.15.4a-2007 */
-	hw->phy->supported.channels[3] |= 0x3fff;
+	hw->phy->supported.page[3].chunk[0].channels |= 0x3fff;
+
+	hw->phy->supported.page[4].nchunks = 3;
 	/* UWB Sub-gigahertz 802.15.4a-2007 */
-	hw->phy->supported.channels[4] |= 1;
+	hw->phy->supported.page[4].chunk[0].channels |= 1;
 	/* UWB Low band 802.15.4a-2007 */
-	hw->phy->supported.channels[4] |= 0x1e;
+	hw->phy->supported.page[4].chunk[1].channels |= 0x1e;
 	/* UWB High band 802.15.4a-2007 */
-	hw->phy->supported.channels[4] |= 0xffe0;
+	hw->phy->supported.page[4].chunk[2].channels |= 0xffe0;
+
+	hw->phy->supported.page[5].nchunks = 2;
 	/* 750 MHz O-QPSK 802.15.4c-2009 */
-	hw->phy->supported.channels[5] |= 0xf;
+	hw->phy->supported.page[5].chunk[0].channels |= 0xf;
 	/* 750 MHz MPSK 802.15.4c-2009 */
-	hw->phy->supported.channels[5] |= 0xf0;
+	hw->phy->supported.page[5].chunk[1].channels |= 0xf0;
+
+	hw->phy->supported.page[6].nchunks = 2;
 	/* 950 MHz BPSK 802.15.4d-2009 */
-	hw->phy->supported.channels[6] |= 0x3ff;
+	hw->phy->supported.page[6].chunk[0].channels |= 0x3ff;
 	/* 950 MHz GFSK 802.15.4d-2009 */
-	hw->phy->supported.channels[6] |= 0x3ffc00;
+	hw->phy->supported.page[6].chunk[1].channels |= 0x3ffc00;
 
 	ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
 	/* fake phy channel 13 as default */
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 5324d0eda223..76fa532d8891 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -744,36 +744,49 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 	phy = hw->priv;
 	phy->hw = hw;
 
+	hw->phy->supported.page[0].nchunks = 3;
 	/* 868 MHz BPSK	802.15.4-2003 */
-	hw->phy->supported.channels[0] |= 1;
+	hw->phy->supported.page[0].chunk[0].channels |= 1;
 	/* 915 MHz BPSK	802.15.4-2003 */
-	hw->phy->supported.channels[0] |= 0x7fe;
+	hw->phy->supported.page[0].chunk[1].channels |= 0x7fe;
 	/* 2.4 GHz O-QPSK 802.15.4-2003 */
-	hw->phy->supported.channels[0] |= 0x7FFF800;
+	hw->phy->supported.page[0].chunk[2].channels |= 0x7FFF800;
+
+	hw->phy->supported.page[1].nchunks = 2;
 	/* 868 MHz ASK 802.15.4-2006 */
-	hw->phy->supported.channels[1] |= 1;
+	hw->phy->supported.page[1].chunk[0].channels |= 1;
 	/* 915 MHz ASK 802.15.4-2006 */
-	hw->phy->supported.channels[1] |= 0x7fe;
+	hw->phy->supported.page[1].chunk[1].channels |= 0x7fe;
+
+	hw->phy->supported.page[2].nchunks = 2;
 	/* 868 MHz O-QPSK 802.15.4-2006 */
-	hw->phy->supported.channels[2] |= 1;
+	hw->phy->supported.page[2].chunk[0].channels |= 1;
 	/* 915 MHz O-QPSK 802.15.4-2006 */
-	hw->phy->supported.channels[2] |= 0x7fe;
+	hw->phy->supported.page[2].chunk[1].channels |= 0x7fe;
+
+	hw->phy->supported.page[3].nchunks = 1;
 	/* 2.4 GHz CSS 802.15.4a-2007 */
-	hw->phy->supported.channels[3] |= 0x3fff;
+	hw->phy->supported.page[3].chunk[0].channels |= 0x3fff;
+
+	hw->phy->supported.page[4].nchunks = 3;
 	/* UWB Sub-gigahertz 802.15.4a-2007 */
-	hw->phy->supported.channels[4] |= 1;
+	hw->phy->supported.page[4].chunk[0].channels |= 1;
 	/* UWB Low band 802.15.4a-2007 */
-	hw->phy->supported.channels[4] |= 0x1e;
+	hw->phy->supported.page[4].chunk[1].channels |= 0x1e;
 	/* UWB High band 802.15.4a-2007 */
-	hw->phy->supported.channels[4] |= 0xffe0;
+	hw->phy->supported.page[4].chunk[2].channels |= 0xffe0;
+
+	hw->phy->supported.page[5].nchunks = 2;
 	/* 750 MHz O-QPSK 802.15.4c-2009 */
-	hw->phy->supported.channels[5] |= 0xf;
+	hw->phy->supported.page[5].chunk[0].channels |= 0xf;
 	/* 750 MHz MPSK 802.15.4c-2009 */
-	hw->phy->supported.channels[5] |= 0xf0;
+	hw->phy->supported.page[5].chunk[1].channels |= 0xf0;
+
+	hw->phy->supported.page[6].nchunks = 2;
 	/* 950 MHz BPSK 802.15.4d-2009 */
-	hw->phy->supported.channels[6] |= 0x3ff;
+	hw->phy->supported.page[6].chunk[0].channels |= 0x3ff;
 	/* 950 MHz GFSK 802.15.4d-2009 */
-	hw->phy->supported.channels[6] |= 0x3ffc00;
+	hw->phy->supported.page[6].chunk[1].channels |= 0x3ffc00;
 
 	ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
 
diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index 8dc04e2590b1..5190c4d4f505 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -1002,7 +1002,8 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 
 	phy->cca.mode = NL802154_CCA_ENERGY;
 
-	phy->supported.channels[0] = MCR20A_VALID_CHANNELS;
+	phy->supported.page[0].nchunks = 1;
+	phy->supported.page[0].chunk[0].channels = MCR20A_VALID_CHANNELS;
 	phy->current_page = 0;
 	/* MCR20A default reset value */
 	phy->current_channel = 20;
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index ff83e00b77af..5a38f3077771 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -1287,7 +1287,8 @@ static int mrf24j40_probe(struct spi_device *spi)
 	spi_set_drvdata(spi, devrec);
 	devrec->hw = hw;
 	devrec->hw->parent = &spi->dev;
-	devrec->hw->phy->supported.channels[0] = CHANNEL_MASK;
+	devrec->hw->phy->supported.page[0].nchunks = 1;
+	devrec->hw->phy->supported.page[0].chunk[0].channels = CHANNEL_MASK;
 	devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
 			    IEEE802154_HW_CSMA_PARAMS |
 			    IEEE802154_HW_PROMISCUOUS;
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 6ed07844eb24..ef49a23801c6 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -131,9 +131,18 @@ wpan_phy_supported_bool(bool b, enum nl802154_supported_bool_states st)
 	return false;
 }
 
+struct phy_channels {
+	u32 channels;
+};
+
+struct phy_page {
+	unsigned int nchunks;
+	struct phy_channels chunk[3];
+};
+
 struct wpan_phy_supported {
-	u32 channels[IEEE802154_MAX_PAGE + 1],
-	    cca_modes, cca_opts, iftypes;
+	struct phy_page page[IEEE802154_MAX_PAGE + 1];
+	u32 cca_modes, cca_opts, iftypes;
 	enum nl802154_supported_bool_states lbt;
 	u8 min_minbe, max_minbe, min_maxbe, max_maxbe,
 	   min_csma_backoffs, max_csma_backoffs;
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
index 1c19f575d574..a0cf6feffc6a 100644
--- a/net/ieee802154/core.h
+++ b/net/ieee802154/core.h
@@ -47,4 +47,6 @@ struct cfg802154_registered_device *
 cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx);
 struct wpan_phy *wpan_phy_idx_to_wpan_phy(int wpan_phy_idx);
 
+u32 cfg802154_get_supported_chans(struct wpan_phy *phy, unsigned int page);
+
 #endif /* __IEEE802154_CORE_H */
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 02f6a53d0faa..304d6951cdf7 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -32,6 +32,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	int i, pages = 0;
 	uint32_t *buf = kcalloc(IEEE802154_MAX_PAGE + 1, sizeof(uint32_t),
 				GFP_KERNEL);
+	u32 chans;
 
 	pr_debug("%s\n", __func__);
 
@@ -49,8 +50,11 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
 		goto nla_put_failure;
 	for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
-		if (phy->supported.channels[i])
-			buf[pages++] = phy->supported.channels[i] | (i << 27);
+		chans = cfg802154_get_supported_chans(phy, i);
+		if (!chans)
+			continue;
+
+		buf[pages++] = chans | (i << 27);
 	}
 	if (pages &&
 	    nla_put(msg, IEEE802154_ATTR_CHANNEL_PAGE_LIST,
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 277124f206e0..45e2c9b0505a 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -320,6 +320,21 @@ nl802154_put_flags(struct sk_buff *msg, int attr, u32 mask)
 	return 0;
 }
 
+u32 cfg802154_get_supported_chans(struct wpan_phy *phy, unsigned int page)
+{
+	struct phy_page *ppage;
+	unsigned int chunk;
+	u32 supported = 0;
+
+	ppage = &phy->supported.page[page];
+
+	for (chunk = 0; chunk <= ppage->nchunks; chunk++)
+		supported |= ppage->chunk[chunk].channels;
+
+	return supported;
+}
+EXPORT_SYMBOL(cfg802154_get_supported_chans);
+
 static int
 nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
 				struct sk_buff *msg)
@@ -333,7 +348,7 @@ nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
 
 	for (page = 0; page <= IEEE802154_MAX_PAGE; page++) {
 		if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL,
-				rdev->wpan_phy.supported.channels[page]))
+				cfg802154_get_supported_chans(&rdev->wpan_phy, page)))
 			return -ENOBUFS;
 	}
 	nla_nest_end(msg, nl_page);
@@ -347,6 +362,7 @@ nl802154_put_capabilities(struct sk_buff *msg,
 {
 	const struct wpan_phy_supported *caps = &rdev->wpan_phy.supported;
 	struct nlattr *nl_caps, *nl_channels;
+	u32 chans;
 	int i;
 
 	nl_caps = nla_nest_start_noflag(msg, NL802154_ATTR_WPAN_PHY_CAPS);
@@ -358,10 +374,12 @@ nl802154_put_capabilities(struct sk_buff *msg,
 		return -ENOBUFS;
 
 	for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
-		if (caps->channels[i]) {
-			if (nl802154_put_flags(msg, i, caps->channels[i]))
-				return -ENOBUFS;
-		}
+		chans = cfg802154_get_supported_chans(&rdev->wpan_phy, i);
+		if (!chans)
+			continue;
+
+		if (nl802154_put_flags(msg, i, chans))
+			return -ENOBUFS;
 	}
 
 	nla_nest_end(msg, nl_channels);
@@ -965,7 +983,7 @@ static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
 
 	/* check 802.15.4 constraints */
 	if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL ||
-	    !(rdev->wpan_phy.supported.channels[page] & BIT(channel)))
+	    !(cfg802154_get_supported_chans(&rdev->wpan_phy, page) & BIT(channel)))
 		return -EINVAL;
 
 	return rdev_set_channel(rdev, page, channel);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 06/41] net: ieee802154: Give more details to the core about the channel configurations
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (4 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 05/41] net: ieee802154: Improve the way supported channels are declared Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods Miquel Raynal
                   ` (35 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

In order to let the core derive eg. the symbol duration for a given
channel, it needs to know which protocol is being used, on which band,
and eventually more details such as the mean PRF in the case of UWB.

Create the necessary enumerations to declare all of that. Include them
in the currently-almost-empty phy_channels structure which until now
only declared the supported channels as bitfields.

The PRF is declared in a union as this clearly is a parameter that does
not apply to most of the protocols. It is very likely that other
parameters will get added in the future to further define specific
protocols and the union will likely be a good location for them.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/at86rf230.c       | 29 ++++++++++++++---
 drivers/net/ieee802154/atusb.c           | 29 ++++++++++++++---
 drivers/net/ieee802154/ca8210.c          |  3 ++
 drivers/net/ieee802154/mac802154_hwsim.c | 33 +++++++++++++++++++
 drivers/net/ieee802154/mcr20a.c          |  3 ++
 include/net/cfg802154.h                  | 41 ++++++++++++++++++++++++
 6 files changed, 130 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index cdf5d2a4f763..1feabeed17fb 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -1560,6 +1560,8 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->data = &at86rf231_data;
 		lp->hw->phy->supported.page[0].nchunks = 1;
 		lp->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
+		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		lp->hw->phy->current_channel = 11;
 		lp->hw->phy->symbol_duration = 16;
 		lp->hw->phy->supported.tx_powers = at86rf231_powers;
@@ -1571,10 +1573,27 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		chip = "at86rf212";
 		lp->data = &at86rf212_data;
 		lp->hw->flags |= IEEE802154_HW_LBT;
-		lp->hw->phy->supported.page[0].nchunks = 1;
-		lp->hw->phy->supported.page[0].chunk[0].channels = 0x00007FF;
-		lp->hw->phy->supported.page[2].nchunks = 1;
-		lp->hw->phy->supported.page[2].chunk[0].channels = 0x00007FF;
+
+		lp->hw->phy->supported.page[0].nchunks = 2;
+		/* SUB:0 and BPSK:0 -> BPSK-20 */
+		lp->hw->phy->supported.page[0].chunk[0].channels = 1;
+		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_BPSK_PHY;
+		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_868_MHZ_BAND;
+		/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
+		lp->hw->phy->supported.page[0].chunk[1].channels = 0x00007FE;
+		lp->hw->phy->supported.page[0].chunk[1].protocol = IEEE802154_OQPSK_PHY;
+		lp->hw->phy->supported.page[0].chunk[1].band = IEEE802154_868_MHZ_BAND;
+
+		lp->hw->phy->supported.page[2].nchunks = 2;
+		/* SUB:1 and BPSK:0 -> BPSK-40 */
+		lp->hw->phy->supported.page[2].chunk[0].channels = 1;
+		lp->hw->phy->supported.page[2].chunk[0].protocol = IEEE802154_BPSK_PHY;
+		lp->hw->phy->supported.page[2].chunk[0].band = IEEE802154_915_MHZ_BAND;
+		/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
+		lp->hw->phy->supported.page[2].chunk[1].channels = 0x00007FE;
+		lp->hw->phy->supported.page[2].chunk[1].protocol = IEEE802154_OQPSK_PHY;
+		lp->hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
+
 		lp->hw->phy->current_channel = 5;
 		lp->hw->phy->symbol_duration = 25;
 		lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
@@ -1588,6 +1607,8 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->data = &at86rf233_data;
 		lp->hw->phy->supported.page[0].nchunks = 1;
 		lp->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
+		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		lp->hw->phy->current_channel = 13;
 		lp->hw->phy->symbol_duration = 16;
 		lp->hw->phy->supported.tx_powers = at86rf233_powers;
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 38ebfacf2698..7e8c9d6db7d7 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -916,6 +916,8 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		chip = "AT86RF230";
 		atusb->hw->phy->supported.page[0].nchunks = 1;
 		atusb->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
+		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
 		atusb->hw->phy->symbol_duration = 16;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
@@ -927,6 +929,8 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		chip = "AT86RF231";
 		atusb->hw->phy->supported.page[0].nchunks = 1;
 		atusb->hw->phy->supported.page[0].chunk[0].channels = 0x7FFF800;
+		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
 		atusb->hw->phy->symbol_duration = 16;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
@@ -937,10 +941,27 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 	case 7:
 		chip = "AT86RF212";
 		atusb->hw->flags |= IEEE802154_HW_LBT;
-		atusb->hw->phy->supported.page[0].nchunks = 1;
-		atusb->hw->phy->supported.page[0].chunk[0].channels = 0x00007FF;
-		atusb->hw->phy->supported.page[2].nchunks = 1;
-		atusb->hw->phy->supported.page[2].chunk[0].channels = 0x00007FF;
+
+		atusb->hw->phy->supported.page[0].nchunks = 2;
+		/* SUB:0 and BPSK:0 -> BPSK-20 */
+		atusb->hw->phy->supported.page[0].chunk[0].channels = 1;
+		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_BPSK_PHY;
+		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_868_MHZ_BAND;
+		/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
+		atusb->hw->phy->supported.page[0].chunk[1].channels = 0x00007FE;
+		atusb->hw->phy->supported.page[0].chunk[1].protocol = IEEE802154_OQPSK_PHY;
+		atusb->hw->phy->supported.page[0].chunk[1].band = IEEE802154_868_MHZ_BAND;
+
+		atusb->hw->phy->supported.page[2].nchunks = 2;
+		/* SUB:1 and BPSK:0 -> BPSK-40 */
+		atusb->hw->phy->supported.page[2].chunk[0].channels = 1;
+		atusb->hw->phy->supported.page[2].chunk[0].protocol = IEEE802154_BPSK_PHY;
+		atusb->hw->phy->supported.page[2].chunk[0].band = IEEE802154_915_MHZ_BAND;
+		/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
+		atusb->hw->phy->supported.page[2].chunk[1].channels = 0x00007FE;
+		atusb->hw->phy->supported.page[2].chunk[1].protocol = IEEE802154_OQPSK_PHY;
+		atusb->hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
+
 		atusb->hw->phy->current_channel = 5;
 		atusb->hw->phy->symbol_duration = 25;
 		atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 1a667fceb8ba..f42a0b719a33 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2963,7 +2963,10 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
 {
 	/* Support channels 11-26 */
 	ca8210_hw->phy->supported.page[0].nchunks = 1;
+	/* 2.4 GHz O-QPSK */
 	ca8210_hw->phy->supported.page[0].chunk[0].channels = CA8210_VALID_CHANNELS;
+	ca8210_hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+	ca8210_hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 	ca8210_hw->phy->supported.tx_powers_size = CA8210_MAX_TX_POWERS;
 	ca8210_hw->phy->supported.tx_powers = ca8210_tx_powers;
 	ca8210_hw->phy->supported.cca_ed_levels_size = CA8210_MAX_ED_LEVELS;
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 76fa532d8891..583fcdf7d267 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -747,46 +747,79 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 	hw->phy->supported.page[0].nchunks = 3;
 	/* 868 MHz BPSK	802.15.4-2003 */
 	hw->phy->supported.page[0].chunk[0].channels |= 1;
+	hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_BPSK_PHY;
+	hw->phy->supported.page[0].chunk[0].band = IEEE802154_868_MHZ_BAND;
 	/* 915 MHz BPSK	802.15.4-2003 */
 	hw->phy->supported.page[0].chunk[1].channels |= 0x7fe;
+	hw->phy->supported.page[0].chunk[1].protocol = IEEE802154_BPSK_PHY;
+	hw->phy->supported.page[0].chunk[1].band = IEEE802154_915_MHZ_BAND;
 	/* 2.4 GHz O-QPSK 802.15.4-2003 */
 	hw->phy->supported.page[0].chunk[2].channels |= 0x7FFF800;
+	hw->phy->supported.page[0].chunk[2].protocol = IEEE802154_OQPSK_PHY;
+	hw->phy->supported.page[0].chunk[2].band = IEEE802154_2400_MHZ_BAND;
 
 	hw->phy->supported.page[1].nchunks = 2;
 	/* 868 MHz ASK 802.15.4-2006 */
 	hw->phy->supported.page[1].chunk[0].channels |= 1;
+	hw->phy->supported.page[1].chunk[0].protocol = IEEE802154_ASK_PHY;
+	hw->phy->supported.page[1].chunk[0].band = IEEE802154_868_MHZ_BAND;
 	/* 915 MHz ASK 802.15.4-2006 */
 	hw->phy->supported.page[1].chunk[1].channels |= 0x7fe;
+	hw->phy->supported.page[1].chunk[1].protocol = IEEE802154_ASK_PHY;
+	hw->phy->supported.page[1].chunk[1].band = IEEE802154_915_MHZ_BAND;
 
 	hw->phy->supported.page[2].nchunks = 2;
 	/* 868 MHz O-QPSK 802.15.4-2006 */
 	hw->phy->supported.page[2].chunk[0].channels |= 1;
+	hw->phy->supported.page[2].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+	hw->phy->supported.page[2].chunk[0].band = IEEE802154_868_MHZ_BAND;
 	/* 915 MHz O-QPSK 802.15.4-2006 */
 	hw->phy->supported.page[2].chunk[1].channels |= 0x7fe;
+	hw->phy->supported.page[2].chunk[1].protocol = IEEE802154_OQPSK_PHY;
+	hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
 
 	hw->phy->supported.page[3].nchunks = 1;
 	/* 2.4 GHz CSS 802.15.4a-2007 */
 	hw->phy->supported.page[3].chunk[0].channels |= 0x3fff;
+	hw->phy->supported.page[3].chunk[0].protocol = IEEE802154_CSS_PHY;
+	hw->phy->supported.page[3].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 
 	hw->phy->supported.page[4].nchunks = 3;
 	/* UWB Sub-gigahertz 802.15.4a-2007 */
 	hw->phy->supported.page[4].chunk[0].channels |= 1;
+	hw->phy->supported.page[4].chunk[0].protocol = IEEE802154_HRP_UWB_PHY;
+	hw->phy->supported.page[4].chunk[0].band = IEEE802154_250_750_MHZ_BAND;
+	hw->phy->supported.page[4].chunk[0].prf = IEEE802154_62890KHZ_MEAN_PRF;
 	/* UWB Low band 802.15.4a-2007 */
 	hw->phy->supported.page[4].chunk[1].channels |= 0x1e;
+	hw->phy->supported.page[4].chunk[1].protocol = IEEE802154_HRP_UWB_PHY;
+	hw->phy->supported.page[4].chunk[1].band = IEEE802154_3100_4800_MHZ_BAND;
+	hw->phy->supported.page[4].chunk[1].prf = IEEE802154_62890KHZ_MEAN_PRF;
 	/* UWB High band 802.15.4a-2007 */
 	hw->phy->supported.page[4].chunk[2].channels |= 0xffe0;
+	hw->phy->supported.page[4].chunk[2].protocol = IEEE802154_HRP_UWB_PHY;
+	hw->phy->supported.page[4].chunk[2].band = IEEE802154_6000_10600_MHZ_BAND;
+	hw->phy->supported.page[4].chunk[2].prf = IEEE802154_62890KHZ_MEAN_PRF;
 
 	hw->phy->supported.page[5].nchunks = 2;
 	/* 750 MHz O-QPSK 802.15.4c-2009 */
 	hw->phy->supported.page[5].chunk[0].channels |= 0xf;
+	hw->phy->supported.page[5].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+	hw->phy->supported.page[5].chunk[0].band = IEEE802154_750_MHZ_BAND;
 	/* 750 MHz MPSK 802.15.4c-2009 */
 	hw->phy->supported.page[5].chunk[1].channels |= 0xf0;
+	hw->phy->supported.page[5].chunk[1].protocol = IEEE802154_MQPSK_PHY;
+	hw->phy->supported.page[5].chunk[1].band = IEEE802154_750_MHZ_BAND;
 
 	hw->phy->supported.page[6].nchunks = 2;
 	/* 950 MHz BPSK 802.15.4d-2009 */
 	hw->phy->supported.page[6].chunk[0].channels |= 0x3ff;
+	hw->phy->supported.page[6].chunk[0].protocol = IEEE802154_BPSK_PHY;
+	hw->phy->supported.page[6].chunk[0].band = IEEE802154_950_MHZ_BAND;
 	/* 950 MHz GFSK 802.15.4d-2009 */
 	hw->phy->supported.page[6].chunk[1].channels |= 0x3ffc00;
+	hw->phy->supported.page[6].chunk[1].protocol = IEEE802154_GFSK_PHY;
+	hw->phy->supported.page[6].chunk[1].band = IEEE802154_950_MHZ_BAND;
 
 	ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
 
diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index 5190c4d4f505..f0eb2d3b1c4e 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -1003,7 +1003,10 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 	phy->cca.mode = NL802154_CCA_ENERGY;
 
 	phy->supported.page[0].nchunks = 1;
+	/* 2.4 GHz O-QPSK */
 	phy->supported.page[0].chunk[0].channels = MCR20A_VALID_CHANNELS;
+	phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
+	phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 	phy->current_page = 0;
 	/* MCR20A default reset value */
 	phy->current_channel = 20;
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index ef49a23801c6..03c8008217fb 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -131,8 +131,49 @@ wpan_phy_supported_bool(bool b, enum nl802154_supported_bool_states st)
 	return false;
 }
 
+enum ieee802154_phy_protocols {
+	IEEE802154_UNKNOWN_PHY,
+	IEEE802154_BPSK_PHY,
+	IEEE802154_OQPSK_PHY,
+	IEEE802154_MQPSK_PHY,
+	IEEE802154_GFSK_PHY,
+	IEEE802154_ASK_PHY,
+	IEEE802154_CSS_PHY,
+	IEEE802154_HRP_UWB_PHY,
+
+	IEEE802154_MAX_PHY,
+};
+
+enum ieee802154_phy_bands {
+	IEEE802154_UNKNOWN_BAND,
+	IEEE802154_750_MHZ_BAND,
+	IEEE802154_868_MHZ_BAND,
+	IEEE802154_915_MHZ_BAND,
+	IEEE802154_950_MHZ_BAND,
+	IEEE802154_2400_MHZ_BAND,
+	IEEE802154_250_750_MHZ_BAND,
+	IEEE802154_3100_4800_MHZ_BAND,
+	IEEE802154_6000_10600_MHZ_BAND,
+
+	IEEE802154_MAX_BAND,
+};
+
+enum ieee802154_phy_mean_prfs {
+	IEEE802154_UNKNOWN_MEAN_PRF,
+	IEEE802154_16100KHZ_MEAN_PRF,
+	IEEE802154_4030KHZ_MEAN_PRF,
+	IEEE802154_62890KHZ_MEAN_PRF,
+
+	IEEE802154_MAX_PRF,
+};
+
 struct phy_channels {
 	u32 channels;
+	enum ieee802154_phy_protocols protocol;
+	enum ieee802154_phy_bands band;
+	union {
+		enum ieee802154_phy_mean_prfs prf;
+	};
 };
 
 struct phy_page {
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (5 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 06/41] net: ieee802154: Give more details to the core about the channel configurations Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 22:52   ` Alexander Aring
  2022-01-17 11:54 ` [PATCH v3 08/41] net: mac802154: Convert the symbol duration into nanoseconds Miquel Raynal
                   ` (34 subsequent siblings)
  41 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

These periods are expressed in time units (microseconds) while 40 and 12
are the number of symbol durations these periods will last. We need to
multiply them both with phy->symbol_duration in order to get these
values in microseconds.

Fixes: 8c6ad9cc5157 ("ieee802154: Add NXP MCR20A IEEE 802.15.4 transceiver driver")
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/mcr20a.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index f0eb2d3b1c4e..e2c249aef430 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -976,8 +976,8 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 	dev_dbg(printdev(lp), "%s\n", __func__);
 
 	phy->symbol_duration = 16;
-	phy->lifs_period = 40;
-	phy->sifs_period = 12;
+	phy->lifs_period = 40 * phy->symbol_duration;
+	phy->sifs_period = 12 * phy->symbol_duration;
 
 	hw->flags = IEEE802154_HW_TX_OMIT_CKSUM |
 			IEEE802154_HW_AFILT |
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 08/41] net: mac802154: Convert the symbol duration into nanoseconds
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (6 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 09/41] net: mac802154: Set the symbol duration automatically Miquel Raynal
                   ` (33 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Tdsym is often given in the spec as pretty small numbers in microseconds
and hence was reflected in the code as symbol_duration and was stored as
a u8. Actually, for UWB PHYs, the symbol duration is given in
nanoseconds and are as precise as picoseconds. In order to handle better
these PHYs, change the type of symbol_duration to u32 and store this
value in nanoseconds.

All the users of this variable are updated in a mechanical change.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/at86rf230.c | 22 +++++++++++-----------
 drivers/net/ieee802154/atusb.c     | 22 +++++++++++-----------
 drivers/net/ieee802154/ca8210.c    |  2 +-
 drivers/net/ieee802154/mcr20a.c    |  8 ++++----
 include/net/cfg802154.h            |  4 ++--
 net/mac802154/main.c               |  8 ++++----
 6 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 1feabeed17fb..e58b0dc64364 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -1066,24 +1066,24 @@ at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
 	if (channel == 0) {
 		if (page == 0) {
 			/* SUB:0 and BPSK:0 -> BPSK-20 */
-			lp->hw->phy->symbol_duration = 50;
+			lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC;
 		} else {
 			/* SUB:1 and BPSK:0 -> BPSK-40 */
-			lp->hw->phy->symbol_duration = 25;
+			lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
 		}
 	} else {
 		if (page == 0)
 			/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
-			lp->hw->phy->symbol_duration = 40;
+			lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC;
 		else
 			/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
-			lp->hw->phy->symbol_duration = 16;
+			lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 	}
 
-	lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD *
-				   lp->hw->phy->symbol_duration;
-	lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD *
-				   lp->hw->phy->symbol_duration;
+	lp->hw->phy->lifs_period =
+		(IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
+	lp->hw->phy->sifs_period =
+		(IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
 
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
@@ -1563,7 +1563,7 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		lp->hw->phy->current_channel = 11;
-		lp->hw->phy->symbol_duration = 16;
+		lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		lp->hw->phy->supported.tx_powers = at86rf231_powers;
 		lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers);
 		lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels;
@@ -1595,7 +1595,7 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
 
 		lp->hw->phy->current_channel = 5;
-		lp->hw->phy->symbol_duration = 25;
+		lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
 		lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
 		lp->hw->phy->supported.tx_powers = at86rf212_powers;
 		lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
@@ -1610,7 +1610,7 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		lp->hw->phy->current_channel = 13;
-		lp->hw->phy->symbol_duration = 16;
+		lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		lp->hw->phy->supported.tx_powers = at86rf233_powers;
 		lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers);
 		lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels;
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 7e8c9d6db7d7..80382919520e 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -678,24 +678,24 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 	if (channel == 0) {
 		if (page == 0) {
 			/* SUB:0 and BPSK:0 -> BPSK-20 */
-			lp->hw->phy->symbol_duration = 50;
+			lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC;
 		} else {
 			/* SUB:1 and BPSK:0 -> BPSK-40 */
-			lp->hw->phy->symbol_duration = 25;
+			lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
 		}
 	} else {
 		if (page == 0)
 			/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
-			lp->hw->phy->symbol_duration = 40;
+			lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC;
 		else
 			/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
-			lp->hw->phy->symbol_duration = 16;
+			lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 	}
 
-	lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD *
-				   lp->hw->phy->symbol_duration;
-	lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD *
-				   lp->hw->phy->symbol_duration;
+	lp->hw->phy->lifs_period =
+		(IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
+	lp->hw->phy->sifs_period =
+		(IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
 
 	return atusb_write_subreg(lp, SR_CHANNEL, channel);
 }
@@ -919,7 +919,7 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
-		atusb->hw->phy->symbol_duration = 16;
+		atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
 		atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
 		hw->phy->supported.cca_ed_levels = atusb_ed_levels;
@@ -932,7 +932,7 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
-		atusb->hw->phy->symbol_duration = 16;
+		atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
 		atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
 		hw->phy->supported.cca_ed_levels = atusb_ed_levels;
@@ -963,7 +963,7 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		atusb->hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
 
 		atusb->hw->phy->current_channel = 5;
-		atusb->hw->phy->symbol_duration = 25;
+		atusb->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
 		atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
 		atusb->hw->phy->supported.tx_powers = at86rf212_powers;
 		atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index f42a0b719a33..6bd970d26220 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2977,7 +2977,7 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
 	ca8210_hw->phy->cca.mode = NL802154_CCA_ENERGY_CARRIER;
 	ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND;
 	ca8210_hw->phy->cca_ed_level = -9800;
-	ca8210_hw->phy->symbol_duration = 16;
+	ca8210_hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 	ca8210_hw->phy->lifs_period = 40;
 	ca8210_hw->phy->sifs_period = 12;
 	ca8210_hw->flags =
diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index e2c249aef430..34063b7e663e 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -975,9 +975,9 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 
 	dev_dbg(printdev(lp), "%s\n", __func__);
 
-	phy->symbol_duration = 16;
-	phy->lifs_period = 40 * phy->symbol_duration;
-	phy->sifs_period = 12 * phy->symbol_duration;
+	phy->symbol_duration = 16 * NSEC_PER_USEC;
+	phy->lifs_period = (40 * phy->symbol_duration) / NSEC_PER_USEC;
+	phy->sifs_period = (12 * phy->symbol_duration) / NSEC_PER_USEC;
 
 	hw->flags = IEEE802154_HW_TX_OMIT_CKSUM |
 			IEEE802154_HW_AFILT |
@@ -1010,7 +1010,7 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 	phy->current_page = 0;
 	/* MCR20A default reset value */
 	phy->current_channel = 20;
-	phy->symbol_duration = 16;
+	phy->symbol_duration = 16 * NSEC_PER_USEC;
 	phy->supported.tx_powers = mcr20a_powers;
 	phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers);
 	phy->cca_ed_level = phy->supported.cca_ed_levels[75];
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 03c8008217fb..286709a9dd0b 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -253,8 +253,8 @@ struct wpan_phy {
 
 	/* PHY depended MAC PIB values */
 
-	/* 802.15.4 acronym: Tdsym in usec */
-	u8 symbol_duration;
+	/* 802.15.4 acronym: Tdsym in nsec */
+	u32 symbol_duration;
 	/* lifs and sifs periods timing */
 	u16 lifs_period;
 	u16 sifs_period;
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 520cedc594e1..53153367f9d0 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -131,10 +131,10 @@ static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy)
 	 * Should be done when all drivers sets this value.
 	 */
 
-	wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD *
-				wpan_phy->symbol_duration;
-	wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD *
-				wpan_phy->symbol_duration;
+	wpan_phy->lifs_period =
+		(IEEE802154_LIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
+	wpan_phy->sifs_period =
+		(IEEE802154_SIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
 }
 
 int ieee802154_register_hw(struct ieee802154_hw *hw)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 09/41] net: mac802154: Set the symbol duration automatically
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (7 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 08/41] net: mac802154: Convert the symbol duration into nanoseconds Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 10/41] net: ieee802154: Drop duration settings when the core does it already Miquel Raynal
                   ` (32 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Now that we have access to all the basic information to know which
symbol duration should be applied, let's set the symbol duration
automatically. The two locations that must call for the symbol duration
to be set are:
- when manually requesting a channel change though the netlink interface
- at PHY creation, ieee802154_alloc_hw() already calls
  ieee802154_change_channel() which will now update the symbol duration
  accordingly.

If an information is missing, the symbol duration is not touched, a
debug message is eventually printed. This keeps the compatibility with
the unconverted drivers for which it was too complicated for me to find
their precise information. If they initially provided a symbol duration,
it would be kept. If they don't, the symbol duration value is left
untouched.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h |   2 +
 net/mac802154/cfg.c     |   1 +
 net/mac802154/main.c    | 105 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 286709a9dd0b..4491e2724ff2 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -455,4 +455,6 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
 	return dev_name(&phy->dev);
 }
 
+void ieee802154_configure_durations(struct wpan_phy *phy);
+
 #endif /* __NET_CFG802154_H */
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index fbeebe3bc31d..1e4a9f74ed43 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -118,6 +118,7 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 	if (!ret) {
 		wpan_phy->current_page = page;
 		wpan_phy->current_channel = channel;
+		ieee802154_configure_durations(wpan_phy);
 	}
 
 	return ret;
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 53153367f9d0..f08c34c27ea9 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -113,6 +113,109 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 }
 EXPORT_SYMBOL(ieee802154_alloc_hw);
 
+void ieee802154_configure_durations(struct wpan_phy *phy)
+{
+	struct phy_page *page = &phy->supported.page[phy->current_page];
+	struct phy_channels *chan;
+	bool valid_band = false;
+	unsigned int chunk;
+	u32 duration = 0;
+
+	for (chunk = 0; chunk < page->nchunks; chunk++) {
+		if (page->chunk[chunk].channels & BIT(phy->current_channel))
+			break;
+	}
+
+	if (chunk == page->nchunks) {
+		pr_debug("Wrong channels description\n");
+		return;
+	}
+
+	chan = &page->chunk[chunk];
+	switch (chan->protocol) {
+	case IEEE802154_BPSK_PHY:
+		switch (chan->band) {
+		case IEEE802154_868_MHZ_BAND:
+			/* 868 MHz BPSK	802.15.4-2003: 20 ksym/s */
+			duration = 50 * NSEC_PER_USEC;
+			break;
+		case IEEE802154_915_MHZ_BAND:
+			/* 915 MHz BPSK	802.15.4-2003: 40 ksym/s */
+			duration = 25 * NSEC_PER_USEC;
+			break;
+		default:
+			break;
+		}
+		break;
+	case IEEE802154_OQPSK_PHY:
+		switch (chan->band) {
+		case IEEE802154_868_MHZ_BAND:
+			/* 868 MHz O-QPSK 802.15.4-2006: 25 ksym/s */
+			duration = 40 * NSEC_PER_USEC;
+			break;
+		case IEEE802154_915_MHZ_BAND:
+		case IEEE802154_2400_MHZ_BAND:
+			/* 915/2400 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
+			duration = 16 * NSEC_PER_USEC;
+			break;
+		default:
+			break;
+		}
+		break;
+	case IEEE802154_CSS_PHY:
+		switch (chan->band) {
+		case IEEE802154_2400_MHZ_BAND:
+			/* 2.4 GHz CSS 802.15.4a-2007: 1/6 Msym/s */
+			duration = 6 * NSEC_PER_USEC;
+			break;
+		default:
+			break;
+		}
+		break;
+	case IEEE802154_HRP_UWB_PHY:
+		switch (chan->band) {
+		case IEEE802154_250_750_MHZ_BAND:
+		case IEEE802154_3100_4800_MHZ_BAND:
+		case IEEE802154_6000_10600_MHZ_BAND:
+			valid_band = true;
+			break;
+		default:
+			break;
+		}
+
+		if (!valid_band)
+			break;
+
+		/* UWB 802.15.4a-2007: 993.6 or 1017.6 or 3974.4 ns */
+		switch (chan->prf) {
+		case IEEE802154_16100KHZ_MEAN_PRF:
+			duration = 994;
+			break;
+		case IEEE802154_4030KHZ_MEAN_PRF:
+			duration = 3974;
+			break;
+		case IEEE802154_62890KHZ_MEAN_PRF:
+			duration = 1018;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (!duration) {
+		pr_debug("Unknown PHY symbol duration\n");
+		return;
+	}
+
+	phy->symbol_duration = duration;
+	phy->lifs_period = (IEEE802154_LIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC;
+	phy->sifs_period = (IEEE802154_SIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC;
+}
+EXPORT_SYMBOL(ieee802154_configure_durations);
+
 void ieee802154_free_hw(struct ieee802154_hw *hw)
 {
 	struct ieee802154_local *local = hw_to_local(hw);
@@ -157,6 +260,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 
 	ieee802154_setup_wpan_phy_pib(local->phy);
 
+	ieee802154_configure_durations(local->phy);
+
 	if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) {
 		local->phy->supported.min_csma_backoffs = 4;
 		local->phy->supported.max_csma_backoffs = 4;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 10/41] net: ieee802154: Drop duration settings when the core does it already
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (8 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 09/41] net: mac802154: Set the symbol duration automatically Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 11/41] net: ieee802154: Move IEEE 802.15.4 Kconfig main entry Miquel Raynal
                   ` (31 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

The core now knows how to set the symbol duration in a few cases, when
drivers correctly advertise the protocols used on each channel. For
these drivers, there is no more need to bother with symbol duration,
lifs and sifs periods so just drop the duplicated code.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/at86rf230.c | 33 ------------------------------
 drivers/net/ieee802154/atusb.c     | 33 ------------------------------
 drivers/net/ieee802154/ca8210.c    |  1 -
 drivers/net/ieee802154/mcr20a.c    |  5 -----
 4 files changed, 72 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index e58b0dc64364..583f835c317a 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -1055,36 +1055,6 @@ at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
 	if (rc < 0)
 		return rc;
 
-	/* This sets the symbol_duration according frequency on the 212.
-	 * TODO move this handling while set channel and page in cfg802154.
-	 * We can do that, this timings are according 802.15.4 standard.
-	 * If we do that in cfg802154, this is a more generic calculation.
-	 *
-	 * This should also protected from ifs_timer. Means cancel timer and
-	 * init with a new value. For now, this is okay.
-	 */
-	if (channel == 0) {
-		if (page == 0) {
-			/* SUB:0 and BPSK:0 -> BPSK-20 */
-			lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC;
-		} else {
-			/* SUB:1 and BPSK:0 -> BPSK-40 */
-			lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
-		}
-	} else {
-		if (page == 0)
-			/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
-			lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC;
-		else
-			/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
-			lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
-	}
-
-	lp->hw->phy->lifs_period =
-		(IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
-	lp->hw->phy->sifs_period =
-		(IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
-
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
 
@@ -1563,7 +1533,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		lp->hw->phy->current_channel = 11;
-		lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		lp->hw->phy->supported.tx_powers = at86rf231_powers;
 		lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers);
 		lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels;
@@ -1595,7 +1564,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
 
 		lp->hw->phy->current_channel = 5;
-		lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
 		lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
 		lp->hw->phy->supported.tx_powers = at86rf212_powers;
 		lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
@@ -1610,7 +1578,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
 		lp->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		lp->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		lp->hw->phy->current_channel = 13;
-		lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		lp->hw->phy->supported.tx_powers = at86rf233_powers;
 		lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers);
 		lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels;
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 80382919520e..1a56073c1c52 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -667,36 +667,6 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 	if (rc < 0)
 		return rc;
 
-	/* This sets the symbol_duration according frequency on the 212.
-	 * TODO move this handling while set channel and page in cfg802154.
-	 * We can do that, this timings are according 802.15.4 standard.
-	 * If we do that in cfg802154, this is a more generic calculation.
-	 *
-	 * This should also protected from ifs_timer. Means cancel timer and
-	 * init with a new value. For now, this is okay.
-	 */
-	if (channel == 0) {
-		if (page == 0) {
-			/* SUB:0 and BPSK:0 -> BPSK-20 */
-			lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC;
-		} else {
-			/* SUB:1 and BPSK:0 -> BPSK-40 */
-			lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
-		}
-	} else {
-		if (page == 0)
-			/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
-			lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC;
-		else
-			/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
-			lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
-	}
-
-	lp->hw->phy->lifs_period =
-		(IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
-	lp->hw->phy->sifs_period =
-		(IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000;
-
 	return atusb_write_subreg(lp, SR_CHANNEL, channel);
 }
 
@@ -919,7 +889,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
-		atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
 		atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
 		hw->phy->supported.cca_ed_levels = atusb_ed_levels;
@@ -932,7 +901,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		atusb->hw->phy->supported.page[0].chunk[0].protocol = IEEE802154_OQPSK_PHY;
 		atusb->hw->phy->supported.page[0].chunk[0].band = IEEE802154_2400_MHZ_BAND;
 		atusb->hw->phy->current_channel = 11;	/* reset default */
-		atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 		atusb->hw->phy->supported.tx_powers = atusb_powers;
 		atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
 		hw->phy->supported.cca_ed_levels = atusb_ed_levels;
@@ -963,7 +931,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb)
 		atusb->hw->phy->supported.page[2].chunk[1].band = IEEE802154_915_MHZ_BAND;
 
 		atusb->hw->phy->current_channel = 5;
-		atusb->hw->phy->symbol_duration = 25 * NSEC_PER_USEC;
 		atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
 		atusb->hw->phy->supported.tx_powers = at86rf212_powers;
 		atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 6bd970d26220..d3a9e4fe05f4 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2977,7 +2977,6 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
 	ca8210_hw->phy->cca.mode = NL802154_CCA_ENERGY_CARRIER;
 	ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND;
 	ca8210_hw->phy->cca_ed_level = -9800;
-	ca8210_hw->phy->symbol_duration = 16 * NSEC_PER_USEC;
 	ca8210_hw->phy->lifs_period = 40;
 	ca8210_hw->phy->sifs_period = 12;
 	ca8210_hw->flags =
diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index 34063b7e663e..8d12c2968302 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -975,10 +975,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 
 	dev_dbg(printdev(lp), "%s\n", __func__);
 
-	phy->symbol_duration = 16 * NSEC_PER_USEC;
-	phy->lifs_period = (40 * phy->symbol_duration) / NSEC_PER_USEC;
-	phy->sifs_period = (12 * phy->symbol_duration) / NSEC_PER_USEC;
-
 	hw->flags = IEEE802154_HW_TX_OMIT_CKSUM |
 			IEEE802154_HW_AFILT |
 			IEEE802154_HW_PROMISCUOUS;
@@ -1010,7 +1006,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
 	phy->current_page = 0;
 	/* MCR20A default reset value */
 	phy->current_channel = 20;
-	phy->symbol_duration = 16 * NSEC_PER_USEC;
 	phy->supported.tx_powers = mcr20a_powers;
 	phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers);
 	phy->cca_ed_level = phy->supported.cca_ed_levels[75];
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 11/41] net: ieee802154: Move IEEE 802.15.4 Kconfig main entry
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (9 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 10/41] net: ieee802154: Drop duration settings when the core does it already Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 12/41] net: mac802154: Include the softMAC stack inside the IEEE 802.15.4 menu Miquel Raynal
                   ` (30 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

It makes certainly more sense to have all the low-range wireless
protocols such as Bluetooth, IEEE 802.11 (WiFi) and IEEE 802.15.4
together, so let's move the main IEEE 802.15.4 stack Kconfig entry at a
better location.

Signed-off-by: David Girault <david.girault@qorvo.com>
[miquel.raynal@bootlin.com: Isolate this change from a bigger commit and
rewrite the commit message.]
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/Kconfig b/net/Kconfig
index 8a1f9d0287de..0da89d09ffa6 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -228,7 +228,6 @@ source "net/x25/Kconfig"
 source "net/lapb/Kconfig"
 source "net/phonet/Kconfig"
 source "net/6lowpan/Kconfig"
-source "net/ieee802154/Kconfig"
 source "net/mac802154/Kconfig"
 source "net/sched/Kconfig"
 source "net/dcb/Kconfig"
@@ -380,6 +379,7 @@ source "net/mac80211/Kconfig"
 
 endif # WIRELESS
 
+source "net/ieee802154/Kconfig"
 source "net/rfkill/Kconfig"
 source "net/9p/Kconfig"
 source "net/caif/Kconfig"
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 12/41] net: mac802154: Include the softMAC stack inside the IEEE 802.15.4 menu
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (10 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 11/41] net: ieee802154: Move IEEE 802.15.4 Kconfig main entry Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 13/41] net: ieee802154: Move the address structure earlier Miquel Raynal
                   ` (29 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

The softMAC stack has no meaning outside of the IEEE 802.15.4 stack and
cannot be used without it.

Signed-off-by: David Girault <david.girault@qorvo.com>
[miquel.raynal@bootlin.com: Isolate this change from a bigger commit]
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/Kconfig            | 1 -
 net/ieee802154/Kconfig | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/Kconfig b/net/Kconfig
index 0da89d09ffa6..a5e31078fd14 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -228,7 +228,6 @@ source "net/x25/Kconfig"
 source "net/lapb/Kconfig"
 source "net/phonet/Kconfig"
 source "net/6lowpan/Kconfig"
-source "net/mac802154/Kconfig"
 source "net/sched/Kconfig"
 source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig
index 31aed75fe62d..7e4b1d49d445 100644
--- a/net/ieee802154/Kconfig
+++ b/net/ieee802154/Kconfig
@@ -36,6 +36,7 @@ config IEEE802154_SOCKET
 	  for 802.15.4 dataframes. Also RAW socket interface to build MAC
 	  header from userspace.
 
+source "net/mac802154/Kconfig"
 source "net/ieee802154/6lowpan/Kconfig"
 
 endif
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 13/41] net: ieee802154: Move the address structure earlier
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (11 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 12/41] net: mac802154: Include the softMAC stack inside the IEEE 802.15.4 menu Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 14/41] net: ieee802154: Add a kernel doc header to the ieee802154_addr structure Miquel Raynal
                   ` (28 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

Move the address structure earlier in the cfg802154.h header in order to
use it in subsequent additions. There is no functional change here.

Signed-off-by: David Girault <david.girault@qorvo.com>
[miquel.raynal@bootlin.com: Isolate this change from a bigger commit]
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 4491e2724ff2..4193c242d96e 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -29,6 +29,15 @@ struct ieee802154_llsec_key_id;
 struct ieee802154_llsec_key;
 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 
+struct ieee802154_addr {
+	u8 mode;
+	__le16 pan_id;
+	union {
+		__le16 short_addr;
+		__le64 extended_addr;
+	};
+};
+
 struct cfg802154_ops {
 	struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
 							   const char *name,
@@ -277,15 +286,6 @@ static inline void wpan_phy_net_set(struct wpan_phy *wpan_phy, struct net *net)
 	write_pnet(&wpan_phy->_net, net);
 }
 
-struct ieee802154_addr {
-	u8 mode;
-	__le16 pan_id;
-	union {
-		__le16 short_addr;
-		__le64 extended_addr;
-	};
-};
-
 struct ieee802154_llsec_key_id {
 	u8 mode;
 	u8 id;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 14/41] net: ieee802154: Add a kernel doc header to the ieee802154_addr structure
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (12 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 13/41] net: ieee802154: Move the address structure earlier Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 15/41] net: ieee802154: Return meaningful error codes from the netlink helpers Miquel Raynal
                   ` (27 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

While not being absolutely needed, it at least explain the mode vs. enum
fields.

Signed-off-by: David Girault <david.girault@qorvo.com>
[miquel.raynal@bootlin.com: Isolate this change from a bigger commit and
                            reword the comment]
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 4193c242d96e..0b8b1812cea1 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -29,6 +29,16 @@ struct ieee802154_llsec_key_id;
 struct ieee802154_llsec_key;
 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 
+/**
+ * struct ieee802154_addr - IEEE802.15.4 device address
+ * @mode: Address mode from frame header. Can be one of:
+ *        - @IEEE802154_ADDR_NONE
+ *        - @IEEE802154_ADDR_SHORT
+ *        - @IEEE802154_ADDR_LONG
+ * @pan_id: The PAN ID this address belongs to
+ * @short_addr: address if @mode is @IEEE802154_ADDR_SHORT
+ * @extended_addr: address if @mode is @IEEE802154_ADDR_LONG
+ */
 struct ieee802154_addr {
 	u8 mode;
 	__le16 pan_id;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 15/41] net: ieee802154: Return meaningful error codes from the netlink helpers
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (13 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 14/41] net: ieee802154: Add a kernel doc header to the ieee802154_addr structure Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 16/41] net: mac802154: Explain the use of ieee802154_wake/stop_queue() Miquel Raynal
                   ` (26 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Returning -1 does not indicate anything useful.

Use a standard and meaningful error code instead.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/ieee802154/nl802154.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 45e2c9b0505a..bd1015611a7e 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -1459,7 +1459,7 @@ static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid,
 
 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
 	if (!hdr)
-		return -1;
+		return -ENOBUFS;
 
 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
 		goto nla_put_failure;
@@ -1652,7 +1652,7 @@ static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid,
 
 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
 	if (!hdr)
-		return -1;
+		return -ENOBUFS;
 
 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
 		goto nla_put_failure;
@@ -1830,7 +1830,7 @@ static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid,
 
 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
 	if (!hdr)
-		return -1;
+		return -ENOBUFS;
 
 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
 		goto nla_put_failure;
@@ -2006,7 +2006,7 @@ static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid,
 
 	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
 	if (!hdr)
-		return -1;
+		return -ENOBUFS;
 
 	if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
 		goto nla_put_failure;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 16/41] net: mac802154: Explain the use of ieee802154_wake/stop_queue()
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (14 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 15/41] net: ieee802154: Return meaningful error codes from the netlink helpers Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over Miquel Raynal
                   ` (25 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

It is not straightforward to the newcomer that a single skb can be sent
at a time and that the internal process is to stop the queue when
processing a frame before re-enabling it. Make this clear by documenting
the ieee802154_wake/stop_queue() helpers.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/mac802154.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index d524ffb9eb25..94b2e3008e77 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -464,6 +464,12 @@ void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
  * ieee802154_wake_queue - wake ieee802154 queue
  * @hw: pointer as obtained from ieee802154_alloc_hw().
  *
+ * Tranceivers have either one transmit framebuffer or one framebuffer for both
+ * transmitting and receiving. Hence, the core only handles one frame at a time
+ * for each phy, which means we had to stop the queue to avoid new skb to come
+ * during the transmission. The queue then needs to be woken up after the
+ * operation.
+ *
  * Drivers should use this function instead of netif_wake_queue.
  */
 void ieee802154_wake_queue(struct ieee802154_hw *hw);
@@ -472,6 +478,12 @@ void ieee802154_wake_queue(struct ieee802154_hw *hw);
  * ieee802154_stop_queue - stop ieee802154 queue
  * @hw: pointer as obtained from ieee802154_alloc_hw().
  *
+ * Tranceivers have either one transmit framebuffer or one framebuffer for both
+ * transmitting and receiving. Hence, the core only handles one frame at a time
+ * for each phy, which means we need to tell upper layers to stop giving us new
+ * skbs while we are busy with the transmitted one. The queue must then be
+ * stopped before transmitting.
+ *
  * Drivers should use this function instead of netif_stop_queue.
  */
 void ieee802154_stop_queue(struct ieee802154_hw *hw);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (15 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 16/41] net: mac802154: Explain the use of ieee802154_wake/stop_queue() Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 22:58   ` Alexander Aring
  2022-01-18  0:34   ` Alexander Aring
  2022-01-17 11:54 ` [PATCH v3 18/41] net: ieee802154: atusb: " Miquel Raynal
                   ` (24 subsequent siblings)
  41 siblings, 2 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

ieee802154_xmit_complete() is the right helper to call when a
transmission is over. The fact that it completed or not is not really a
question, but drivers must tell the core that the completion is over,
even if it was canceled. Do not call ieee802154_wake_queue() manually,
in order to let full control of this task to the core.

By using the complete helper we also avoid leacking the skb structure.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/at86rf230.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 583f835c317a..1941e1f3d2ef 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
 	if (ctx->free)
 		kfree(ctx);
 
-	ieee802154_wake_queue(lp->hw);
+	ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
 }
 
 static void
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 18/41] net: ieee802154: atusb: Call the complete helper when a transmission is over
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (16 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 19/41] net: ieee802154: ca8210: " Miquel Raynal
                   ` (23 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

ieee802154_xmit_complete() is the right helper to call when a
transmission is over. The fact that it completed or not is not really a
question, but drivers must tell the core that the completion is over,
even if it was canceled. Do not call ieee802154_wake_queue() manually,
in order to let full control of this task to the core.

Here the skb is freed with a particular helper because it is done in irq
context. It is not necessary to do that as the *_xmit_complete() helper
will handle it properly anyway.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/atusb.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 1a56073c1c52..4bc7b2dcbdd2 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -262,19 +262,16 @@ static void atusb_tx_done(struct atusb *atusb, u8 seq)
 	u8 expect = atusb->tx_ack_seq;
 
 	dev_dbg(&usb_dev->dev, "%s (0x%02x/0x%02x)\n", __func__, seq, expect);
-	if (seq == expect) {
-		/* TODO check for ifs handling in firmware */
-		ieee802154_xmit_complete(atusb->hw, atusb->tx_skb, false);
-	} else {
-		/* TODO I experience this case when atusb has a tx complete
-		 * irq before probing, we should fix the firmware it's an
-		 * unlikely case now that seq == expect is then true, but can
-		 * happen and fail with a tx_skb = NULL;
-		 */
-		ieee802154_wake_queue(atusb->hw);
-		if (atusb->tx_skb)
-			dev_kfree_skb_irq(atusb->tx_skb);
-	}
+
+	/* TODO:
+	 * seq == expect: Check for ifs handling in firmware.
+	 * seq != expect: I experience this case when atusb has a tx complete
+	 * irq before probing, we should fix the firmware it's an unlikely case
+	 * now that seq == expect is then true, but can happen and fail with a
+	 * tx_skb = NULL;
+	 */
+
+	ieee802154_xmit_complete(atusb->hw, atusb->tx_skb, false);
 }
 
 static void atusb_in_good(struct urb *urb)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 19/41] net: ieee802154: ca8210: Call the complete helper when a transmission is over
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (17 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 18/41] net: ieee802154: atusb: " Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 20/41] net: mac802154: Stop exporting ieee802154_wake/stop_queue() Miquel Raynal
                   ` (22 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

ieee802154_xmit_complete() is the right helper to call when a
transmission is over. The fact that it completed or not is not really a
question, but drivers must tell the core that the completion is over,
even if it was canceled. Do not call ieee802154_wake_queue() manually,
in order to let full control of this task to the core.

Here the two paths are equivalent of calling *_xmit_complete() with its
ifs_handling parameter set to true or false, so let's use it instead of
open coding it.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/ca8210.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index d3a9e4fe05f4..374827f51dff 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -1750,6 +1750,7 @@ static int ca8210_async_xmit_complete(
 	u8                     status)
 {
 	struct ca8210_priv *priv = hw->priv;
+	bool ifs_handling = true;
 
 	if (priv->nextmsduhandle != msduhandle) {
 		dev_err(
@@ -1770,10 +1771,8 @@ static int ca8210_async_xmit_complete(
 			"Link transmission unsuccessful, status = %d\n",
 			status
 		);
-		if (status != MAC_TRANSACTION_OVERFLOW) {
-			ieee802154_wake_queue(priv->hw);
-			return 0;
-		}
+		if (status != MAC_TRANSACTION_OVERFLOW)
+			ifs_handling = false;
 	}
 	ieee802154_xmit_complete(priv->hw, priv->tx_skb, true);
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 20/41] net: mac802154: Stop exporting ieee802154_wake/stop_queue()
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (18 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 19/41] net: ieee802154: ca8210: " Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 21/41] net: mac802154: Rename the synchronous xmit worker Miquel Raynal
                   ` (21 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Individual drivers do not necessarily need to call these helpers
manually. There are other functions, more suited for this purpose, that
will do that for them. The advantage is that, as no more drivers call
these, it eases the tracking of the ongoing transfers that we are about
to introduce while keeping the possibility to bypass thse counters from
core code.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/mac802154.h      | 27 ---------------------------
 net/mac802154/ieee802154_i.h | 24 ++++++++++++++++++++++++
 net/mac802154/util.c         |  2 --
 3 files changed, 24 insertions(+), 29 deletions(-)

diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 94b2e3008e77..13798867b8d3 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -460,33 +460,6 @@ void ieee802154_unregister_hw(struct ieee802154_hw *hw);
  */
 void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
 			   u8 lqi);
-/**
- * ieee802154_wake_queue - wake ieee802154 queue
- * @hw: pointer as obtained from ieee802154_alloc_hw().
- *
- * Tranceivers have either one transmit framebuffer or one framebuffer for both
- * transmitting and receiving. Hence, the core only handles one frame at a time
- * for each phy, which means we had to stop the queue to avoid new skb to come
- * during the transmission. The queue then needs to be woken up after the
- * operation.
- *
- * Drivers should use this function instead of netif_wake_queue.
- */
-void ieee802154_wake_queue(struct ieee802154_hw *hw);
-
-/**
- * ieee802154_stop_queue - stop ieee802154 queue
- * @hw: pointer as obtained from ieee802154_alloc_hw().
- *
- * Tranceivers have either one transmit framebuffer or one framebuffer for both
- * transmitting and receiving. Hence, the core only handles one frame at a time
- * for each phy, which means we need to tell upper layers to stop giving us new
- * skbs while we are busy with the transmitted one. The queue must then be
- * stopped before transmitting.
- *
- * Drivers should use this function instead of netif_stop_queue.
- */
-void ieee802154_stop_queue(struct ieee802154_hw *hw);
 
 /**
  * ieee802154_xmit_complete - frame transmission complete
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 702560acc8ce..97b66088532b 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -128,6 +128,30 @@ netdev_tx_t
 ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
 enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer);
 
+/**
+ * ieee802154_wake_queue - wake ieee802154 queue
+ * @hw: pointer as obtained from ieee802154_alloc_hw().
+ *
+ * Tranceivers have either one transmit framebuffer or one framebuffer for both
+ * transmitting and receiving. Hence, the core only handles one frame at a time
+ * for each phy, which means we had to stop the queue to avoid new skb to come
+ * during the transmission. The queue then needs to be woken up after the
+ * operation.
+ */
+void ieee802154_wake_queue(struct ieee802154_hw *hw);
+
+/**
+ * ieee802154_stop_queue - stop ieee802154 queue
+ * @hw: pointer as obtained from ieee802154_alloc_hw().
+ *
+ * Tranceivers have either one transmit framebuffer or one framebuffer for both
+ * transmitting and receiving. Hence, the core only handles one frame at a time
+ * for each phy, which means we need to tell upper layers to stop giving us new
+ * skbs while we are busy with the transmitted one. The queue must then be
+ * stopped before transmitting.
+ */
+void ieee802154_stop_queue(struct ieee802154_hw *hw);
+
 /* MIB callbacks */
 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
 
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
index f2078238718b..e093ccaebd76 100644
--- a/net/mac802154/util.c
+++ b/net/mac802154/util.c
@@ -27,7 +27,6 @@ void ieee802154_wake_queue(struct ieee802154_hw *hw)
 	}
 	rcu_read_unlock();
 }
-EXPORT_SYMBOL(ieee802154_wake_queue);
 
 void ieee802154_stop_queue(struct ieee802154_hw *hw)
 {
@@ -43,7 +42,6 @@ void ieee802154_stop_queue(struct ieee802154_hw *hw)
 	}
 	rcu_read_unlock();
 }
-EXPORT_SYMBOL(ieee802154_stop_queue);
 
 enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer)
 {
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 21/41] net: mac802154: Rename the synchronous xmit worker
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (19 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 20/41] net: mac802154: Stop exporting ieee802154_wake/stop_queue() Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 22/41] net: mac802154: Rename the main tx_work struct Miquel Raynal
                   ` (20 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

There are currently two driver hooks: one is synchronous, the other is
not. We cannot rely on driver implementations to provide a synchronous
API (which is related to the bus medium more than a wish to have a
synchronized implementation) so we are going to introduce a sync API
above any kind of driver transmit function. In order to clarify what
this worker is for (synchronous driver implementation), let's rename it
so that people don't get bothered by the fact that their driver does not
make use of the "xmit worker" which is a too generic name.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/ieee802154_i.h | 2 +-
 net/mac802154/main.c         | 4 +++-
 net/mac802154/tx.c           | 2 +-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 97b66088532b..b4882b2d7688 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -121,7 +121,7 @@ ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata)
 extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
 
 void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
-void ieee802154_xmit_worker(struct work_struct *work);
+void ieee802154_xmit_sync_worker(struct work_struct *work);
 netdev_tx_t
 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
 netdev_tx_t
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index f08c34c27ea9..a938e49bf5dc 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -95,7 +95,9 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	skb_queue_head_init(&local->skb_queue);
 
-	INIT_WORK(&local->tx_work, ieee802154_xmit_worker);
+	INIT_WORK(&local->tx_work, ieee802154_xmit_sync_worker);
+	INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_work);
+	INIT_DELAYED_WORK(&local->beacons_work, mac802154_beacons_work);
 
 	/* init supported flags with 802.15.4 default ranges */
 	phy->supported.max_minbe = 8;
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index c829e4a75325..97df5985b830 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -22,7 +22,7 @@
 #include "ieee802154_i.h"
 #include "driver-ops.h"
 
-void ieee802154_xmit_worker(struct work_struct *work)
+void ieee802154_xmit_sync_worker(struct work_struct *work)
 {
 	struct ieee802154_local *local =
 		container_of(work, struct ieee802154_local, tx_work);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 22/41] net: mac802154: Rename the main tx_work struct
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (20 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 21/41] net: mac802154: Rename the synchronous xmit worker Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 23/41] net: mac802154: Follow the count of ongoing transmissions Miquel Raynal
                   ` (19 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This entry is dedicated to synchronous transmissions done by drivers
without async hook. Make this clearer that this is not a work that any
driver can use by at least prefixing it with "sync_". While at it, let's
enhance the comment explaining why we choose one or the other.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/ieee802154_i.h | 2 +-
 net/mac802154/main.c         | 2 +-
 net/mac802154/tx.c           | 9 ++++++---
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index b4882b2d7688..18d1f6804810 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -55,7 +55,7 @@ struct ieee802154_local {
 	struct sk_buff_head skb_queue;
 
 	struct sk_buff *tx_skb;
-	struct work_struct tx_work;
+	struct work_struct sync_tx_work;
 };
 
 enum {
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index a938e49bf5dc..43fd4cc13b66 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -95,7 +95,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	skb_queue_head_init(&local->skb_queue);
 
-	INIT_WORK(&local->tx_work, ieee802154_xmit_sync_worker);
+	INIT_WORK(&local->sync_tx_work, ieee802154_xmit_sync_worker);
 	INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_work);
 	INIT_DELAYED_WORK(&local->beacons_work, mac802154_beacons_work);
 
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 97df5985b830..a01689ddd547 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -25,7 +25,7 @@
 void ieee802154_xmit_sync_worker(struct work_struct *work)
 {
 	struct ieee802154_local *local =
-		container_of(work, struct ieee802154_local, tx_work);
+		container_of(work, struct ieee802154_local, sync_tx_work);
 	struct sk_buff *skb = local->tx_skb;
 	struct net_device *dev = skb->dev;
 	int res;
@@ -76,7 +76,10 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	/* Stop the netif queue on each sub_if_data object. */
 	ieee802154_stop_queue(&local->hw);
 
-	/* async is priority, otherwise sync is fallback */
+	/* Drivers should preferably implement the async callback. In some rare
+	 * cases they only provide a sync callback which we will use as a
+	 * fallback.
+	 */
 	if (local->ops->xmit_async) {
 		unsigned int len = skb->len;
 
@@ -90,7 +93,7 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 		dev->stats.tx_bytes += len;
 	} else {
 		local->tx_skb = skb;
-		queue_work(local->workqueue, &local->tx_work);
+		queue_work(local->workqueue, &local->sync_tx_work);
 	}
 
 	return NETDEV_TX_OK;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 23/41] net: mac802154: Follow the count of ongoing transmissions
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (21 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 22/41] net: mac802154: Rename the main tx_work struct Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 24/41] net: mac802154: Hold the transmit queue when relevant Miquel Raynal
                   ` (18 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

In order to create a synchronous API for MLME command purposes, we need
to be able to track the end of the ongoing transmissions. Let's
introduce an atomic variable which is incremented and decremented when
relevant and now at any moment if a there is an ongoing transmission.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h | 3 +++
 net/mac802154/tx.c      | 3 +++
 net/mac802154/util.c    | 1 +
 3 files changed, 7 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 0b8b1812cea1..969cae56b000 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -283,6 +283,9 @@ struct wpan_phy {
 	/* the network namespace this phy lives in currently */
 	possible_net_t _net;
 
+	/* Transmission monitoring */
+	atomic_t ongoing_txs;
+
 	char priv[] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index a01689ddd547..731e86bfe73f 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -45,6 +45,7 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
 	/* Restart the netif queue on each sub_if_data object. */
 	ieee802154_wake_queue(&local->hw);
 	kfree_skb(skb);
+	atomic_dec(&local->phy->ongoing_txs);
 	netdev_dbg(dev, "transmission failed\n");
 }
 
@@ -80,6 +81,7 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	 * cases they only provide a sync callback which we will use as a
 	 * fallback.
 	 */
+	atomic_inc(&local->phy->ongoing_txs);
 	if (local->ops->xmit_async) {
 		unsigned int len = skb->len;
 
@@ -99,6 +101,7 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	return NETDEV_TX_OK;
 
 err_tx:
+	atomic_dec(&local->phy->ongoing_txs);
 	kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
index e093ccaebd76..0fa538b0debc 100644
--- a/net/mac802154/util.c
+++ b/net/mac802154/util.c
@@ -83,6 +83,7 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
 	}
 
 	dev_consume_skb_any(skb);
+	atomic_dec(&hw->phy->ongoing_txs);
 }
 EXPORT_SYMBOL(ieee802154_xmit_complete);
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 24/41] net: mac802154: Hold the transmit queue when relevant
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (22 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 23/41] net: mac802154: Follow the count of ongoing transmissions Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 25/41] net: mac802154: Create a hot tx path Miquel Raynal
                   ` (17 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Let's create a hold_txs atomic variable and increment/decrement it when
relevant. A current use is during a suspend. Very soon we will also use
this feature during scans.

When the variable is incremented, any further call to helpers usually
waking up the queue will skip this part because it is the core
responsibility to wake up the queue when relevant.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h      | 3 ++-
 net/mac802154/cfg.c          | 4 +++-
 net/mac802154/ieee802154_i.h | 5 +++++
 net/mac802154/tx.c           | 7 +++++--
 net/mac802154/util.c         | 8 +++++++-
 5 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 969cae56b000..56aa672e1912 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -283,8 +283,9 @@ struct wpan_phy {
 	/* the network namespace this phy lives in currently */
 	possible_net_t _net;
 
-	/* Transmission monitoring */
+	/* Transmission monitoring and control */
 	atomic_t ongoing_txs;
+	atomic_t hold_txs;
 
 	char priv[] __aligned(NETDEV_ALIGN);
 };
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 1e4a9f74ed43..e8aabf215286 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -46,6 +46,7 @@ static int ieee802154_suspend(struct wpan_phy *wpan_phy)
 	if (!local->open_count)
 		goto suspend;
 
+	atomic_inc(&wpan_phy->hold_txs);
 	ieee802154_stop_queue(&local->hw);
 	synchronize_net();
 
@@ -72,7 +73,8 @@ static int ieee802154_resume(struct wpan_phy *wpan_phy)
 		return ret;
 
 wake_up:
-	ieee802154_wake_queue(&local->hw);
+	if (!atomic_dec_and_test(&wpan_phy->hold_txs))
+		ieee802154_wake_queue(&local->hw);
 	local->suspended = false;
 	return 0;
 }
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 18d1f6804810..0291e49058f2 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -190,6 +190,11 @@ void mac802154_unlock_table(struct net_device *dev);
 
 int mac802154_wpan_update_llsec(struct net_device *dev);
 
+static inline bool mac802154_queue_is_stopped(struct ieee802154_local *local)
+{
+	return atomic_read(&local->phy->hold_txs);
+}
+
 /* interface handling */
 int ieee802154_iface_init(void);
 void ieee802154_iface_exit(void);
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 731e86bfe73f..a8d4d5e175b6 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -43,7 +43,9 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
 
 err_tx:
 	/* Restart the netif queue on each sub_if_data object. */
-	ieee802154_wake_queue(&local->hw);
+	if (!mac802154_queue_is_stopped(local))
+		ieee802154_wake_queue(&local->hw);
+
 	kfree_skb(skb);
 	atomic_dec(&local->phy->ongoing_txs);
 	netdev_dbg(dev, "transmission failed\n");
@@ -87,7 +89,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 
 		ret = drv_xmit_async(local, skb);
 		if (ret) {
-			ieee802154_wake_queue(&local->hw);
+			if (!mac802154_queue_is_stopped(local))
+				ieee802154_wake_queue(&local->hw);
 			goto err_tx;
 		}
 
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
index 0fa538b0debc..db2ac53b937e 100644
--- a/net/mac802154/util.c
+++ b/net/mac802154/util.c
@@ -56,8 +56,13 @@ enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer)
 void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
 			      bool ifs_handling)
 {
+	struct ieee802154_local *local = hw_to_local(hw);
+
+	/* Avoid waking-up a queue which needs to remain stopped */
+	if (mac802154_queue_is_stopped(local))
+		goto after_wakeup;
+
 	if (ifs_handling) {
-		struct ieee802154_local *local = hw_to_local(hw);
 		u8 max_sifs_size;
 
 		/* If transceiver sets CRC on his own we need to use lifs
@@ -82,6 +87,7 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
 		ieee802154_wake_queue(hw);
 	}
 
+after_wakeup:
 	dev_consume_skb_any(skb);
 	atomic_dec(&hw->phy->ongoing_txs);
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 25/41] net: mac802154: Create a hot tx path
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (23 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 24/41] net: mac802154: Hold the transmit queue when relevant Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 26/41] net: mac802154: Add a warning in the hot path Miquel Raynal
                   ` (16 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Let's rename the current tx path to show that this is the "hot" path. We
will soon introduce a slower path for MLME commands.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/tx.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index a8d4d5e175b6..18ee6fcfcd7f 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -109,6 +109,12 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	return NETDEV_TX_OK;
 }
 
+static netdev_tx_t
+ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
+{
+	return ieee802154_tx(local, skb);
+}
+
 netdev_tx_t
 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -116,7 +122,7 @@ ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	skb->skb_iif = dev->ifindex;
 
-	return ieee802154_tx(sdata->local, skb);
+	return ieee802154_hot_tx(sdata->local, skb);
 }
 
 netdev_tx_t
@@ -138,5 +144,5 @@ ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	skb->skb_iif = dev->ifindex;
 
-	return ieee802154_tx(sdata->local, skb);
+	return ieee802154_hot_tx(sdata->local, skb);
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 26/41] net: mac802154: Add a warning in the hot path
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (24 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 25/41] net: mac802154: Create a hot tx path Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 23:14   ` Alexander Aring
  2022-01-17 11:54 ` [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism Miquel Raynal
                   ` (15 subsequent siblings)
  41 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

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.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/tx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 18ee6fcfcd7f..de5ecda80472 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -112,6 +112,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 static netdev_tx_t
 ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
 {
+	WARN_ON(mac802154_queue_is_stopped(local));
+
 	return ieee802154_tx(local, skb);
 }
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (25 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 26/41] net: mac802154: Add a warning in the hot path Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 22:43   ` Alexander Aring
  2022-01-17 11:54 ` [PATCH v3 28/41] net: mac802154: Introduce a synchronous API for MLME commands Miquel Raynal
                   ` (14 subsequent siblings)
  41 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Right now we are able to stop a queue but we have no indication if a
transmission is ongoing or not. We recently introduced an ongoing tx
count variable so let's use it to wake up a queue. Waiters on the queue
will be woken up once all the ongoing transmissions are over. Thanks to
this feature, we will soon be able to introduce a synchronous API.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h      | 1 +
 net/ieee802154/core.c        | 1 +
 net/mac802154/cfg.c          | 1 +
 net/mac802154/ieee802154_i.h | 1 +
 net/mac802154/tx.c           | 6 ++++++
 net/mac802154/util.c         | 1 +
 6 files changed, 11 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 56aa672e1912..0848896120fa 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -286,6 +286,7 @@ struct wpan_phy {
 	/* Transmission monitoring and control */
 	atomic_t ongoing_txs;
 	atomic_t hold_txs;
+	wait_queue_head_t sync_txq;
 
 	char priv[] __aligned(NETDEV_ALIGN);
 };
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index de259b5170ab..0953cacafbff 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -129,6 +129,7 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
 	wpan_phy_net_set(&rdev->wpan_phy, &init_net);
 
 	init_waitqueue_head(&rdev->dev_wait);
+	init_waitqueue_head(&rdev->wpan_phy.sync_txq);
 
 	return &rdev->wpan_phy;
 }
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index e8aabf215286..e2900c9b788c 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -48,6 +48,7 @@ static int ieee802154_suspend(struct wpan_phy *wpan_phy)
 
 	atomic_inc(&wpan_phy->hold_txs);
 	ieee802154_stop_queue(&local->hw);
+	ieee802154_sync_tx(local);
 	synchronize_net();
 
 	/* stop hardware - this must stop RX */
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 0291e49058f2..37d5438fdb3f 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -122,6 +122,7 @@ extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
 
 void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
 void ieee802154_xmit_sync_worker(struct work_struct *work);
+void ieee802154_sync_tx(struct ieee802154_local *local);
 netdev_tx_t
 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
 netdev_tx_t
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index de5ecda80472..d1fd2cc67cbe 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -48,6 +48,7 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
 
 	kfree_skb(skb);
 	atomic_dec(&local->phy->ongoing_txs);
+	wake_up(&local->phy->sync_txq);
 	netdev_dbg(dev, "transmission failed\n");
 }
 
@@ -117,6 +118,11 @@ ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	return ieee802154_tx(local, skb);
 }
 
+void ieee802154_sync_tx(struct ieee802154_local *local)
+{
+	wait_event(local->phy->sync_txq, !atomic_read(&local->phy->ongoing_txs));
+}
+
 netdev_tx_t
 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
index db2ac53b937e..230fe3390df7 100644
--- a/net/mac802154/util.c
+++ b/net/mac802154/util.c
@@ -90,6 +90,7 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
 after_wakeup:
 	dev_consume_skb_any(skb);
 	atomic_dec(&hw->phy->ongoing_txs);
+	wake_up(&hw->phy->sync_txq);
 }
 EXPORT_SYMBOL(ieee802154_xmit_complete);
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 28/41] net: mac802154: Introduce a synchronous API for MLME commands
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (26 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 29/41] net: ieee802154: Add support for internal PAN management Miquel Raynal
                   ` (13 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This is the slow path, we need to wait for each command to be processed
before continuing so let's introduce an helper which does the
transmission and blocks until it gets notified of its asynchronous
completion. This helper is going to be used when introducing scan
support.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/ieee802154_i.h | 1 +
 net/mac802154/tx.c           | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 37d5438fdb3f..40195e2a6f1e 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -123,6 +123,7 @@ extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
 void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
 void ieee802154_xmit_sync_worker(struct work_struct *work);
 void ieee802154_sync_tx(struct ieee802154_local *local);
+void ieee802154_mlme_tx(struct ieee802154_local *local, struct sk_buff *skb);
 netdev_tx_t
 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
 netdev_tx_t
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index d1fd2cc67cbe..334843f66ec4 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -123,6 +123,12 @@ void ieee802154_sync_tx(struct ieee802154_local *local)
 	wait_event(local->phy->sync_txq, !atomic_read(&local->phy->ongoing_txs));
 }
 
+void ieee802154_mlme_tx(struct ieee802154_local *local, struct sk_buff *skb)
+{
+	ieee802154_tx(local, skb);
+	ieee802154_sync_tx(local);
+}
+
 netdev_tx_t
 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 29/41] net: ieee802154: Add support for internal PAN management
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (27 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 28/41] net: mac802154: Introduce a synchronous API for MLME commands Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 30/41] net: ieee802154: Define a beacon frame header Miquel Raynal
                   ` (12 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Let's introduce the basics of PAN management:
- structures defining PANs
- helpers for PANs registration
- helpers discarding old PANs

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h |  31 ++++++
 net/ieee802154/Makefile |   2 +-
 net/ieee802154/core.c   |   2 +
 net/ieee802154/core.h   |  26 +++++
 net/ieee802154/pan.c    | 231 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 291 insertions(+), 1 deletion(-)
 create mode 100644 net/ieee802154/pan.c

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 0848896120fa..8999f87ccac6 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -48,6 +48,24 @@ struct ieee802154_addr {
 	};
 };
 
+/**
+ * struct ieee802154_pan_desc - PAN descriptor information
+ * @coord: PAN ID and coordinator address
+ * @page: page this PAN is on
+ * @channel: channel this PAN is on
+ * @superframe_spec: SuperFrame specification as received
+ * @link_quality: link quality indicator at which the beacon was received
+ * @gts_permit: the PAN coordinator accepts GTS requests
+ */
+struct ieee802154_pan_desc {
+	struct ieee802154_addr *coord;
+	u8 page;
+	u8 channel;
+	u16 superframe_spec;
+	u8 link_quality;
+	bool gts_permit;
+};
+
 struct cfg802154_ops {
 	struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
 							   const char *name,
@@ -472,4 +490,17 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
 
 void ieee802154_configure_durations(struct wpan_phy *phy);
 
+/**
+ * cfg802154_record_pan - Advertize a new PAN following a beacon's reception
+ * @wpan_phy: PHY receiving the beacon
+ * @pan: PAN descriptor
+ *
+ * Tells the internal pan management layer to either register this PAN if it is
+ * new or at least update its entry if already discovered.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int cfg802154_record_pan(struct wpan_phy *wpan_phy,
+			 struct ieee802154_pan_desc *pan);
+
 #endif /* __NET_CFG802154_H */
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index f05b7bdae2aa..6b7c66de730d 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_IEEE802154_SOCKET) += ieee802154_socket.o
 obj-y += 6lowpan/
 
 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \
-                header_ops.o sysfs.o nl802154.o trace.o
+                header_ops.o sysfs.o nl802154.o pan.o trace.o
 ieee802154_socket-y := socket.o
 
 CFLAGS_trace.o := -I$(src)
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 0953cacafbff..7e3e38a30078 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -115,6 +115,8 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
 		kfree(rdev);
 		return NULL;
 	}
+	spin_lock_init(&rdev->pan_lock);
+	INIT_LIST_HEAD(&rdev->pan_list);
 
 	/* atomic_inc_return makes it start at 1, make it start at 0 */
 	rdev->wpan_phy_idx--;
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
index a0cf6feffc6a..0d08d2f79ab9 100644
--- a/net/ieee802154/core.h
+++ b/net/ieee802154/core.h
@@ -22,6 +22,14 @@ struct cfg802154_registered_device {
 	struct list_head wpan_dev_list;
 	int devlist_generation, wpan_dev_id;
 
+	/* pan management */
+	spinlock_t pan_lock;
+	struct list_head pan_list;
+	unsigned int max_pan_entries;
+	unsigned int pan_expiration;
+	unsigned int pan_entries;
+	unsigned int pan_generation;
+
 	/* must be last because of the way we do wpan_phy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN
 	 */
@@ -39,6 +47,17 @@ wpan_phy_to_rdev(struct wpan_phy *wpan_phy)
 extern struct list_head cfg802154_rdev_list;
 extern int cfg802154_rdev_list_generation;
 
+struct cfg802154_internal_pan {
+	struct list_head list;
+	unsigned long discovery_ts;
+	struct ieee802154_pan_desc desc;
+};
+
+/* Always update the list by dropping the expired PANs before iterating */
+#define ieee802154_for_each_pan(pan, rdev)				\
+	cfg802154_expire_pans(rdev);					\
+	list_for_each_entry((pan), &(rdev)->pan_list, list)
+
 int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
 			   struct net *net);
 /* free object */
@@ -49,4 +68,11 @@ struct wpan_phy *wpan_phy_idx_to_wpan_phy(int wpan_phy_idx);
 
 u32 cfg802154_get_supported_chans(struct wpan_phy *phy, unsigned int page);
 
+void cfg802154_set_max_pan_entries(struct cfg802154_registered_device *rdev,
+				   unsigned int max);
+void cfg802154_set_pans_expiration(struct cfg802154_registered_device *rdev,
+				   unsigned int exp_time_s);
+void cfg802154_expire_pans(struct cfg802154_registered_device *rdev);
+void cfg802154_flush_pans(struct cfg802154_registered_device *rdev);
+
 #endif /* __IEEE802154_CORE_H */
diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
new file mode 100644
index 000000000000..1ea15ea1b3bd
--- /dev/null
+++ b/net/ieee802154/pan.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IEEE 802.15.4 PAN management
+ *
+ * Copyright (C) Qorvo, 2021
+ * Authors:
+ *   - David Girault <david.girault@qorvo.com>
+ *   - Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <net/cfg802154.h>
+#include <net/af_ieee802154.h>
+
+#include "ieee802154.h"
+#include "core.h"
+
+static struct cfg802154_internal_pan *
+cfg802154_alloc_pan(struct ieee802154_pan_desc *desc)
+{
+	struct cfg802154_internal_pan *new;
+	struct ieee802154_addr *coord;
+
+	new = kzalloc(sizeof(*new), GFP_KERNEL);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+
+	coord = kzalloc(sizeof(*coord), GFP_KERNEL);
+	if (!coord) {
+		kfree(new);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	new->discovery_ts = jiffies;
+	new->desc = *desc;
+
+	*coord = *desc->coord;
+	new->desc.coord = coord;
+
+	return new;
+}
+
+static void cfg802154_free_pan(struct cfg802154_internal_pan *pan)
+{
+	kfree(pan->desc.coord);
+	kfree(pan);
+}
+
+static void cfg802154_unlink_pan(struct cfg802154_registered_device *rdev,
+				 struct cfg802154_internal_pan *pan)
+{
+	lockdep_assert_held(&rdev->pan_lock);
+
+	list_del(&pan->list);
+	cfg802154_free_pan(pan);
+	rdev->pan_entries--;
+	rdev->pan_generation++;
+}
+
+static void cfg802154_link_pan(struct cfg802154_registered_device *rdev,
+			       struct cfg802154_internal_pan *pan)
+{
+	lockdep_assert_held(&rdev->pan_lock);
+
+	list_add_tail(&pan->list, &rdev->pan_list);
+	rdev->pan_entries++;
+	rdev->pan_generation++;
+}
+
+void cfg802154_set_max_pan_entries(struct cfg802154_registered_device *rdev,
+				   unsigned int max)
+{
+	lockdep_assert_held(&rdev->pan_lock);
+
+	rdev->max_pan_entries = max;
+}
+EXPORT_SYMBOL(cfg802154_set_max_pan_entries);
+
+static bool
+cfg802154_need_to_expire_pans(struct cfg802154_registered_device *rdev)
+{
+	if (!rdev->max_pan_entries)
+		return false;
+
+	if (rdev->pan_entries > rdev->max_pan_entries)
+		return true;
+
+	return false;
+}
+
+void cfg802154_set_pans_expiration(struct cfg802154_registered_device *rdev,
+				   unsigned int exp_time_s)
+{
+	lockdep_assert_held(&rdev->pan_lock);
+
+	rdev->pan_expiration = exp_time_s * HZ;
+}
+EXPORT_SYMBOL(cfg802154_set_pans_expiration);
+
+void cfg802154_expire_pans(struct cfg802154_registered_device *rdev)
+{
+	struct cfg802154_internal_pan *pan, *tmp;
+	unsigned long expiration_time;
+
+	lockdep_assert_held(&rdev->pan_lock);
+
+	if (!rdev->pan_expiration)
+		return;
+
+	expiration_time = jiffies - rdev->pan_expiration;
+	list_for_each_entry_safe(pan, tmp, &rdev->pan_list, list) {
+		if (!time_after(expiration_time, pan->discovery_ts))
+			continue;
+
+		cfg802154_unlink_pan(rdev, pan);
+	}
+}
+EXPORT_SYMBOL(cfg802154_expire_pans);
+
+static void cfg802154_expire_oldest_pan(struct cfg802154_registered_device *rdev)
+{
+	struct cfg802154_internal_pan *pan, *oldest;
+
+	lockdep_assert_held(&rdev->pan_lock);
+
+	if (WARN_ON(list_empty(&rdev->pan_list)))
+		return;
+
+	oldest = list_first_entry(&rdev->pan_list,
+				  struct cfg802154_internal_pan, list);
+
+	list_for_each_entry(pan, &rdev->pan_list, list) {
+		if (!time_before(oldest->discovery_ts, pan->discovery_ts))
+			oldest = pan;
+	}
+
+	cfg802154_unlink_pan(rdev, oldest);
+}
+
+void cfg802154_flush_pans(struct cfg802154_registered_device *rdev)
+{
+	struct cfg802154_internal_pan *pan, *tmp;
+
+	lockdep_assert_held(&rdev->pan_lock);
+
+	list_for_each_entry_safe(pan, tmp, &rdev->pan_list, list)
+		cfg802154_unlink_pan(rdev, pan);
+}
+EXPORT_SYMBOL(cfg802154_flush_pans);
+
+static bool cfg802154_same_pan(struct ieee802154_pan_desc *a,
+			       struct ieee802154_pan_desc *b)
+{
+	int ret;
+
+	if (a->page != b->page)
+		return false;
+
+	if (a->channel != b->channel)
+		return false;
+
+	ret = memcmp(&a->coord->pan_id, &b->coord->pan_id,
+		     sizeof(a->coord->pan_id));
+	if (ret)
+		return false;
+
+	if (a->coord->mode != b->coord->mode)
+		return false;
+
+	if (a->coord->mode == IEEE802154_ADDR_SHORT)
+		ret = memcmp(&a->coord->short_addr, &b->coord->short_addr,
+			     IEEE802154_SHORT_ADDR_LEN);
+	else
+		ret = memcmp(&a->coord->extended_addr, &b->coord->extended_addr,
+			     IEEE802154_EXTENDED_ADDR_LEN);
+
+	return true;
+}
+
+static struct cfg802154_internal_pan *
+cfg802154_find_matching_pan(struct cfg802154_registered_device *rdev,
+			    struct cfg802154_internal_pan *tmp)
+{
+	struct cfg802154_internal_pan *pan;
+
+	list_for_each_entry(pan, &rdev->pan_list, list) {
+		if (cfg802154_same_pan(&pan->desc, &tmp->desc))
+			return pan;
+	}
+
+	return NULL;
+}
+
+static void cfg802154_pan_update(struct cfg802154_registered_device *rdev,
+				 struct cfg802154_internal_pan *new)
+{
+	struct cfg802154_internal_pan *found;
+
+	spin_lock_bh(&rdev->pan_lock);
+
+	found = cfg802154_find_matching_pan(rdev, new);
+	if (found)
+		cfg802154_unlink_pan(rdev, found);
+
+	if (unlikely(cfg802154_need_to_expire_pans(rdev)))
+		cfg802154_expire_oldest_pan(rdev);
+
+	cfg802154_link_pan(rdev, new);
+
+	spin_unlock_bh(&rdev->pan_lock);
+}
+
+int cfg802154_record_pan(struct wpan_phy *wpan_phy,
+			 struct ieee802154_pan_desc *desc)
+{
+	struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
+	struct cfg802154_internal_pan *new;
+
+	new = cfg802154_alloc_pan(desc);
+	if (IS_ERR(new))
+		return (PTR_ERR(new));
+
+	cfg802154_pan_update(rdev, new);
+
+	return 0;
+}
+EXPORT_SYMBOL(cfg802154_record_pan);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 30/41] net: ieee802154: Define a beacon frame header
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (28 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 29/41] net: ieee802154: Add support for internal PAN management Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 31/41] net: ieee802154: Define frame types Miquel Raynal
                   ` (11 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This definition will be used when adding support for scanning and defines
the content of a beacon frame header as in the 802.15.4 specification.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h | 36 +++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index d0d188c3294b..fb6ac354a7b6 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -22,6 +22,42 @@
 
 #include <net/cfg802154.h>
 
+struct ieee802154_beacon_hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	u16 beacon_order:4,
+	    superframe_order:4,
+	    final_cap_slot:4,
+	    battery_life_ext:1,
+	    reserved0:1,
+	    pan_coordinator:1,
+	    assoc_permit:1;
+	u8  gts_count:3,
+	    gts_reserved:4,
+	    gts_permit:1;
+	u8  pend_short_addr_count:3,
+	    reserved1:1,
+	    pend_ext_addr_count:3,
+	    reserved2:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	u16 assoc_permit:1,
+	    pan_coordinator:1,
+	    reserved0:1,
+	    battery_life_ext:1,
+	    final_cap_slot:4,
+	    superframe_order:4,
+	    beacon_order:4;
+	u8  gts_permit:1,
+	    gts_reserved:4,
+	    gts_count:3;
+	u8  reserved2:1,
+	    pend_ext_addr_count:3,
+	    reserved1:1,
+	    pend_short_addr_count:3;
+#else
+#error	"Please fix <asm/byteorder.h>"
+#endif
+} __packed;
+
 struct ieee802154_sechdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
 	u8 level:3,
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 31/41] net: ieee802154: Define frame types
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (29 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 30/41] net: ieee802154: Define a beacon frame header Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 32/41] net: ieee802154: Add support for scanning requests Miquel Raynal
                   ` (10 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

A 802.15.4 frame can be of different types, here is a definition
matching the specification. This enumeration will be soon be used when
adding scanning support.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index fb6ac354a7b6..45dff5d11bc8 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -105,6 +105,17 @@ struct ieee802154_hdr_fc {
 #endif
 };
 
+enum ieee802154_frame_type {
+	IEEE802154_BEACON_FRAME,
+	IEEE802154_DATA_FRAME,
+	IEEE802154_ACKNOWLEDGEMENT_FRAME,
+	IEEE802154_MAC_COMMAND_FRAME,
+	IEEE802154_RESERVED_FRAME,
+	IEEE802154_MULTIPURPOSE_FRAME,
+	IEEE802154_FRAGMENT_FRAME,
+	IEEE802154_EXTENDED_FRAME,
+};
+
 struct ieee802154_hdr {
 	struct ieee802154_hdr_fc fc;
 	u8 seq;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 32/41] net: ieee802154: Add support for scanning requests
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (30 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 31/41] net: ieee802154: Define frame types Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 33/41] net: mac802154: Handle scan requests Miquel Raynal
                   ` (9 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This involves processing triggering scan requests, abort scan requests,
as well as providing information about if the last scan was finished or
not.

A scan request structure is created to list the requirements.

A netlink multicast scan group is also created for the occasion so that
listeners can only focus on scan activity.

Mac layers may now implement the ->trigger_scan() and ->abort_scan()
hooks.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/ieee802154.h |   3 +
 include/net/cfg802154.h    |  26 +++++
 include/net/nl802154.h     |  49 ++++++++
 net/ieee802154/core.h      |   3 +
 net/ieee802154/nl802154.c  | 234 +++++++++++++++++++++++++++++++++++++
 net/ieee802154/nl802154.h  |   4 +
 net/ieee802154/rdev-ops.h  |  28 +++++
 net/ieee802154/trace.h     |  40 +++++++
 8 files changed, 387 insertions(+)

diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index 95c831162212..41178c87c43c 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -44,6 +44,9 @@
 #define IEEE802154_SHORT_ADDR_LEN	2
 #define IEEE802154_PAN_ID_LEN		2
 
+/* Duration in superframe order */
+#define IEEE802154_MAX_SCAN_DURATION	14
+#define IEEE802154_ACTIVE_SCAN_DURATION	15
 #define IEEE802154_LIFS_PERIOD		40
 #define IEEE802154_SIFS_PERIOD		12
 #define IEEE802154_MAX_SIFS_FRAME_SIZE	18
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 8999f87ccac6..15b9cb2c213a 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -66,6 +66,28 @@ struct ieee802154_pan_desc {
 	bool gts_permit;
 };
 
+/**
+ * struct cfg802154_scan_req - Scan request
+ *
+ * @type: type of scan to be performed
+ * @flags: flags bitfield controlling the operation
+ * @page: page on which to perform the scan
+ * @channels: channels in te %page to be scanned
+ * @duration: time spent on each channel, calculated with:
+ *            aBaseSuperframeDuration * (2 ^ duration + 1)
+ * @wpan_dev: the wpan device on which to perform the scan
+ * @wpan_phy: the wpan phy on which to perform the scan
+ */
+struct cfg802154_scan_request {
+	enum nl802154_scan_types type;
+	u32 flags;
+	u8 page;
+	u32 channels;
+	u8 duration;
+	struct wpan_dev *wpan_dev;
+	struct wpan_phy *wpan_phy;
+};
+
 struct cfg802154_ops {
 	struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
 							   const char *name,
@@ -104,6 +126,10 @@ struct cfg802154_ops {
 				struct wpan_dev *wpan_dev, bool mode);
 	int	(*set_ackreq_default)(struct wpan_phy *wpan_phy,
 				      struct wpan_dev *wpan_dev, bool ackreq);
+	int	(*trigger_scan)(struct wpan_phy *wpan_phy,
+				struct cfg802154_scan_request *request);
+	int	(*abort_scan)(struct wpan_phy *wpan_phy,
+			      struct wpan_dev *wpan_dev);
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	void	(*get_llsec_table)(struct wpan_phy *wpan_phy,
 				   struct wpan_dev *wpan_dev,
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 145acb8f2509..51eca3a2b14e 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -58,6 +58,10 @@ enum nl802154_commands {
 
 	NL802154_CMD_SET_WPAN_PHY_NETNS,
 
+	NL802154_CMD_TRIGGER_SCAN,
+	NL802154_CMD_ABORT_SCAN,
+	NL802154_CMD_SCAN_DONE,
+
 	/* add new commands above here */
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -133,6 +137,11 @@ enum nl802154_attrs {
 	NL802154_ATTR_PID,
 	NL802154_ATTR_NETNS_FD,
 
+	NL802154_ATTR_SCAN_TYPE,
+	NL802154_ATTR_SCAN_FLAGS,
+	NL802154_ATTR_SCAN_CHANNELS,
+	NL802154_ATTR_SCAN_DURATION,
+
 	/* add attributes here, update the policy in nl802154.c */
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -218,6 +227,46 @@ enum nl802154_wpan_phy_capability_attr {
 	NL802154_CAP_ATTR_MAX = __NL802154_CAP_ATTR_AFTER_LAST - 1
 };
 
+/**
+ * enum nl802154_scan_types - Scan types
+ *
+ * @__NL802154_SCAN_INVALID: scan type number 0 is reserved
+ * @NL802154_SCAN_ED: An ED scan allows a device to obtain a measure of the peak
+ *	energy in each requested channel
+ * @NL802154_SCAN_ACTIVE: Locate any coordinator transmitting Beacon frames using
+ *	a Beacon Request command
+ * @NL802154_SCAN_PASSIVE: Locate any coordinator transmitting Beacon frames
+ * @NL802154_SCAN_ORPHAN: Relocate coordinator following a loss of synchronisation
+ * @NL802154_SCAN_ENHANCED_ACTIVE: Same as Active using Enhanced Beacon Request
+ *	command instead of Beacon Request command
+ * @NL802154_SCAN_RIT_PASSIVE: Passive scan for RIT Data Request command frames
+ *	instead of Beacon frames
+ * @NL802154_SCAN_ATTR_MAX: Maximum SCAN attribute number
+ */
+enum nl802154_scan_types {
+	__NL802154_SCAN_INVALID,
+	NL802154_SCAN_ED,
+	NL802154_SCAN_ACTIVE,
+	NL802154_SCAN_PASSIVE,
+	NL802154_SCAN_ORPHAN,
+	NL802154_SCAN_ENHANCED_ACTIVE,
+	NL802154_SCAN_RIT_PASSIVE,
+
+	/* keep last */
+	NL802154_SCAN_ATTR_MAX,
+};
+
+/**
+ * enum nl802154_scan_flags - Scan request control flags
+ *
+ * @NL802154_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (ie.
+ *	a different one for every scan iteration). When the flag is set, full
+ *	randomisation is assumed.
+ */
+enum nl802154_scan_flags {
+	NL802154_SCAN_FLAG_RANDOM_ADDR = BIT(0),
+};
+
 /**
  * enum nl802154_cca_modes - cca modes
  *
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
index 0d08d2f79ab9..9aa8f88b6920 100644
--- a/net/ieee802154/core.h
+++ b/net/ieee802154/core.h
@@ -30,6 +30,9 @@ struct cfg802154_registered_device {
 	unsigned int pan_entries;
 	unsigned int pan_generation;
 
+	/* scanning */
+	struct cfg802154_scan_request *scan_req;
+
 	/* must be last because of the way we do wpan_phy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN
 	 */
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index bd1015611a7e..99cbad1f1381 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -26,10 +26,12 @@ static struct genl_family nl802154_fam;
 /* multicast groups */
 enum nl802154_multicast_groups {
 	NL802154_MCGRP_CONFIG,
+	NL802154_MCGRP_SCAN,
 };
 
 static const struct genl_multicast_group nl802154_mcgrps[] = {
 	[NL802154_MCGRP_CONFIG] = { .name = "config", },
+	[NL802154_MCGRP_SCAN] = { .name = "scan", },
 };
 
 /* returns ERR_PTR values */
@@ -216,6 +218,12 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 
 	[NL802154_ATTR_PID] = { .type = NLA_U32 },
 	[NL802154_ATTR_NETNS_FD] = { .type = NLA_U32 },
+
+	[NL802154_ATTR_SCAN_TYPE] = { .type = NLA_U8 },
+	[NL802154_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
+	[NL802154_ATTR_SCAN_CHANNELS] = { .type = NLA_U32 },
+	[NL802154_ATTR_SCAN_DURATION] = { .type = NLA_U8 },
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
 	[NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
@@ -1299,6 +1307,216 @@ static int nl802154_wpan_phy_netns(struct sk_buff *skb, struct genl_info *info)
 	return err;
 }
 
+static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+	struct wpan_phy *wpan_phy = &rdev->wpan_phy;
+	struct cfg802154_scan_request *request;
+	u8 type;
+	int err;
+
+	/* Test iftype and avoid scanning if monitor type. */
+	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
+		return -EOPNOTSUPP;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	if (!request)
+		return -ENOMEM;
+
+	request->wpan_dev = wpan_dev;
+	request->wpan_phy = wpan_phy;
+
+	type = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE]);
+	switch (type) {
+	case NL802154_SCAN_ACTIVE:
+	case NL802154_SCAN_PASSIVE:
+		request->type = type;
+		break;
+	default:
+		pr_err("Invalid scan type: %d\n", type);
+		err = -EINVAL;
+		goto free_request;
+	}
+
+	if (info->attrs[NL802154_ATTR_SCAN_FLAGS])
+		request->flags = nla_get_u32(info->attrs[NL802154_ATTR_SCAN_FLAGS]);
+
+	if (info->attrs[NL802154_ATTR_PAGE]) {
+		request->page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
+		if (request->page > IEEE802154_MAX_PAGE) {
+			pr_err("Invalid page %d > %d\n",
+			       request->page, IEEE802154_MAX_PAGE);
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Use current page by default */
+		request->page = wpan_phy->current_page;
+	}
+
+	if (info->attrs[NL802154_ATTR_SCAN_CHANNELS]) {
+		request->channels = nla_get_u32(info->attrs[NL802154_ATTR_SCAN_CHANNELS]);
+		if (request->channels >= BIT(IEEE802154_MAX_CHANNEL + 1)) {
+			pr_err("Invalid channels bitfield %x ≥ %lx\n",
+			       request->channels,
+			       BIT(IEEE802154_MAX_CHANNEL + 1));
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Scan all supported channels by default */
+		request->channels = cfg802154_get_supported_chans(wpan_phy,
+								  request->page);
+	}
+
+	if (info->attrs[NL802154_ATTR_SCAN_DURATION]) {
+		request->duration = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_DURATION]);
+		if (request->duration > IEEE802154_MAX_SCAN_DURATION) {
+			pr_err("Duration is out of range\n");
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Use maximum duration order by default */
+		request->duration = IEEE802154_MAX_SCAN_DURATION;
+	}
+
+	err = rdev_trigger_scan(rdev, request);
+	if (err) {
+		pr_err("Failure starting scanning (%d)\n", err);
+		goto free_request;
+	}
+
+	rdev->scan_req = request;
+
+	if (wpan_dev->netdev)
+		dev_hold(wpan_dev->netdev);
+
+	return 0;
+
+free_request:
+	kfree(request);
+
+	return err;
+}
+
+static int nl802154_add_scan_req(struct sk_buff *msg,
+				 struct cfg802154_scan_request *req)
+{
+	if (req->type &&
+	    nla_put_u8(msg, NL802154_ATTR_SCAN_TYPE, req->type))
+		goto nla_put_failure;
+
+	if (req->flags &&
+	    nla_put_u32(msg, NL802154_ATTR_SCAN_FLAGS, req->flags))
+		goto nla_put_failure;
+
+	if (req->page &&
+	    nla_put_u8(msg, NL802154_ATTR_PAGE, req->page))
+		goto nla_put_failure;
+
+	if (req->channels &&
+	    nla_put_u32(msg, NL802154_ATTR_SCAN_CHANNELS, req->channels))
+		goto nla_put_failure;
+
+	return 0;
+
+nla_put_failure:
+	return -ENOBUFS;
+}
+
+static int nl802154_prep_scan_msg(struct sk_buff *msg,
+				  struct cfg802154_registered_device *rdev,
+				  struct wpan_dev *wpan_dev,
+				  u32 portid, u32 seq, int flags, u8 cmd)
+{
+	void *hdr;
+
+	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx))
+		goto nla_put_failure;
+
+	if (wpan_dev->netdev &&
+	    nla_put_u32(msg, NL802154_ATTR_IFINDEX, wpan_dev->netdev->ifindex))
+		goto nla_put_failure;
+
+	if (nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
+			      wpan_dev_id(wpan_dev), NL802154_ATTR_PAD))
+		goto nla_put_failure;
+
+	if (nl802154_add_scan_req(msg, rdev->scan_req))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+
+	return -EMSGSIZE;
+}
+
+static int nl802154_send_scan_done_msg(struct cfg802154_registered_device *rdev,
+				       struct wpan_dev *wpan_dev)
+{
+	struct sk_buff *msg;
+	int ret;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	ret = nl802154_prep_scan_msg(msg, rdev, wpan_dev, 0, 0, 0,
+				     NL802154_CMD_SCAN_DONE);
+	if (ret < 0) {
+		nlmsg_free(msg);
+		return ret;
+	}
+
+	return genlmsg_multicast_netns(&nl802154_fam,
+				       wpan_phy_net(&rdev->wpan_phy), msg, 0,
+				       NL802154_MCGRP_SCAN, GFP_KERNEL);
+}
+
+int nl802154_send_scan_done(struct cfg802154_registered_device *rdev,
+			    struct wpan_dev *wpan_dev)
+{
+	int err;
+
+	err = nl802154_send_scan_done_msg(rdev, wpan_dev);
+
+	/* Ignore errors when there are no listeners */
+	if (err == -ESRCH)
+		err = 0;
+
+	if (wpan_dev->netdev)
+		dev_put(wpan_dev->netdev);
+
+	kfree(rdev->scan_req);
+	rdev->scan_req = NULL;
+
+	return err;
+}
+EXPORT_SYMBOL(nl802154_send_scan_done);
+
+static int nl802154_abort_scan(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+
+	/* Resources will be released in the notification helper above when we
+	 * are sure all actions have ended.
+	 */
+	return rdev_abort_scan(rdev, wpan_dev);
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
 	[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
@@ -2387,6 +2605,22 @@ static const struct genl_ops nl802154_ops[] = {
 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
 				  NL802154_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL802154_CMD_TRIGGER_SCAN,
+		.doit = nl802154_trigger_scan,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_CHECK_NETDEV_UP |
+				  NL802154_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL802154_CMD_ABORT_SCAN,
+		.doit = nl802154_abort_scan,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_CHECK_NETDEV_UP |
+				  NL802154_FLAG_NEED_RTNL,
+	},
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	{
 		.cmd = NL802154_CMD_SET_SEC_PARAMS,
diff --git a/net/ieee802154/nl802154.h b/net/ieee802154/nl802154.h
index 8c4b6d08954c..84567cd4ea83 100644
--- a/net/ieee802154/nl802154.h
+++ b/net/ieee802154/nl802154.h
@@ -2,7 +2,11 @@
 #ifndef __IEEE802154_NL802154_H
 #define __IEEE802154_NL802154_H
 
+#include "core.h"
+
 int nl802154_init(void);
 void nl802154_exit(void);
+int nl802154_send_scan_done(struct cfg802154_registered_device *rdev,
+			    struct wpan_dev *wpan_dev);
 
 #endif /* __IEEE802154_NL802154_H */
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h
index 598f5af49775..e171d74c3251 100644
--- a/net/ieee802154/rdev-ops.h
+++ b/net/ieee802154/rdev-ops.h
@@ -209,6 +209,34 @@ rdev_set_ackreq_default(struct cfg802154_registered_device *rdev,
 	return ret;
 }
 
+static inline int rdev_trigger_scan(struct cfg802154_registered_device *rdev,
+				    struct cfg802154_scan_request *request)
+{
+	int ret;
+
+	if (!rdev->ops->trigger_scan)
+		return -EOPNOTSUPP;
+
+	trace_802154_rdev_trigger_scan(&rdev->wpan_phy, request);
+	ret = rdev->ops->trigger_scan(&rdev->wpan_phy, request);
+	trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+	return ret;
+}
+
+static inline int rdev_abort_scan(struct cfg802154_registered_device *rdev,
+				  struct wpan_dev *wpan_dev)
+{
+	int ret;
+
+	if (!rdev->ops->abort_scan)
+		return -EOPNOTSUPP;
+
+	trace_802154_rdev_abort_scan(&rdev->wpan_phy, wpan_dev);
+	ret = rdev->ops->abort_scan(&rdev->wpan_phy, wpan_dev);
+	trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 /* TODO this is already a nl802154, so move into ieee802154 */
 static inline void
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h
index 19c2e5d60e76..e5405f737ded 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -295,6 +295,46 @@ TRACE_EVENT(802154_rdev_set_ackreq_default,
 		WPAN_DEV_PR_ARG, BOOL_TO_STR(__entry->ackreq))
 );
 
+TRACE_EVENT(802154_rdev_trigger_scan,
+	TP_PROTO(struct wpan_phy *wpan_phy,
+		 struct cfg802154_scan_request *request),
+	TP_ARGS(wpan_phy, request),
+	TP_STRUCT__entry(
+		WPAN_PHY_ENTRY
+		__field(u8, page)
+		__field(u32, channels)
+		__field(u8, duration)
+	),
+	TP_fast_assign(
+		WPAN_PHY_ASSIGN;
+		__entry->page = request->page;
+		__entry->channels = request->channels;
+		__entry->duration = request->duration;
+	),
+	TP_printk(WPAN_PHY_PR_FMT ", scan, page: %d, channels: %x, duration %d",
+		  WPAN_PHY_PR_ARG, __entry->page, __entry->channels, __entry->duration)
+);
+
+DECLARE_EVENT_CLASS(802154_wdev_template,
+	TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
+	TP_ARGS(wpan_phy, wpan_dev),
+	TP_STRUCT__entry(
+		WPAN_PHY_ENTRY
+		WPAN_DEV_ENTRY
+	),
+	TP_fast_assign(
+		WPAN_PHY_ASSIGN;
+		WPAN_DEV_ASSIGN;
+	),
+	TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT,
+		  WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG)
+);
+
+DEFINE_EVENT(802154_wdev_template, 802154_rdev_abort_scan,
+	TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
+	TP_ARGS(wpan_phy, wpan_dev)
+);
+
 TRACE_EVENT(802154_rdev_return_int,
 	TP_PROTO(struct wpan_phy *wpan_phy, int ret),
 	TP_ARGS(wpan_phy, ret),
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 33/41] net: mac802154: Handle scan requests
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (31 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 32/41] net: ieee802154: Add support for scanning requests Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 34/41] net: ieee802154: Full PAN management Miquel Raynal
                   ` (8 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Implement the core hooks in order to provide the softMAC layer support
for scan requests and aborts.

Changing the channels is prohibited during the scan.

As transceiver enter in a promiscuous mode during scans, they might stop
checking frame validity so we ensure this gets done at mac level.

The implementation uses a workqueue triggered at a certain interval
depending on the symbol duration for the current channel and the
duration order provided.

Received beacons during a passive scanning procedure are processed and
either registered in the list of known PANs or the existing entry gets
updated accordingly.

Active scanning is not supported yet.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/ieee802154.h   |   4 +
 include/net/mac802154.h      |  14 ++
 net/mac802154/Makefile       |   2 +-
 net/mac802154/cfg.c          |  39 ++++++
 net/mac802154/ieee802154_i.h |  22 +++
 net/mac802154/main.c         |   2 +-
 net/mac802154/rx.c           |  21 ++-
 net/mac802154/scan.c         | 259 +++++++++++++++++++++++++++++++++++
 net/mac802154/tx.c           |   3 +
 net/mac802154/util.c         |  26 ++++
 10 files changed, 385 insertions(+), 7 deletions(-)
 create mode 100644 net/mac802154/scan.c

diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index 41178c87c43c..57bf5317338e 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -47,6 +47,10 @@
 /* Duration in superframe order */
 #define IEEE802154_MAX_SCAN_DURATION	14
 #define IEEE802154_ACTIVE_SCAN_DURATION	15
+/* Superframe duration in slots */
+#define IEEE802154_SUPERFRAME_PERIOD	16
+/* Various periods expressed in symbols */
+#define IEEE802154_SLOT_PERIOD		60
 #define IEEE802154_LIFS_PERIOD		40
 #define IEEE802154_SIFS_PERIOD		12
 #define IEEE802154_MAX_SIFS_FRAME_SIZE	18
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 13798867b8d3..a2eec8786628 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -471,4 +471,18 @@ void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
 void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
 			      bool ifs_handling);
 
+/**
+ * ieee802154_queue_delayed_work - add work onto the mac802154 workqueue
+ *
+ * Drivers and mac802154 use this to queue delayed work onto the mac802154
+ * workqueue.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @dwork: delayable work to queue onto the mac802154 workqueue
+ * @delay: number of jiffies to wait before queueing
+ */
+void ieee802154_queue_delayed_work(struct ieee802154_hw *hw,
+				   struct delayed_work *dwork,
+				   unsigned long delay);
+
 #endif /* NET_MAC802154_H */
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 4059295fdbf8..43d1347b37ee 100644
--- a/net/mac802154/Makefile
+++ b/net/mac802154/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_MAC802154)	+= mac802154.o
 mac802154-objs		:= main.o rx.o tx.o mac_cmd.o mib.o \
-			   iface.o llsec.o util.o cfg.o trace.o
+			   iface.o llsec.o util.o cfg.o scan.o trace.o
 
 CFLAGS_trace.o := -I$(src)
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index e2900c9b788c..958b609b8c1b 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -117,6 +117,10 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 	    wpan_phy->current_channel == channel)
 		return 0;
 
+	/* Refuse to change channels during a scanning operation */
+	if (mac802154_scan_is_ongoing(local))
+		return -EBUSY;
+
 	ret = drv_set_channel(local, page, channel);
 	if (!ret) {
 		wpan_phy->current_page = page;
@@ -264,6 +268,39 @@ ieee802154_set_ackreq_default(struct wpan_phy *wpan_phy,
 	return 0;
 }
 
+static int mac802154_trigger_scan(struct wpan_phy *wpan_phy,
+				  struct cfg802154_scan_request *req)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	struct ieee802154_sub_if_data *sdata;
+	int ret;
+
+	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(req->wpan_dev);
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->scan_lock);
+	ret = mac802154_trigger_scan_locked(sdata, req);
+	mutex_unlock(&local->scan_lock);
+
+	return ret;
+}
+
+static int mac802154_abort_scan(struct wpan_phy *wpan_phy,
+				struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	int ret;
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->scan_lock);
+	ret = mac802154_abort_scan_locked(local);
+	mutex_unlock(&local->scan_lock);
+
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static void
 ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -471,6 +508,8 @@ const struct cfg802154_ops mac802154_config_ops = {
 	.set_max_frame_retries = ieee802154_set_max_frame_retries,
 	.set_lbt_mode = ieee802154_set_lbt_mode,
 	.set_ackreq_default = ieee802154_set_ackreq_default,
+	.trigger_scan = mac802154_trigger_scan,
+	.abort_scan = mac802154_abort_scan,
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	.get_llsec_table = ieee802154_get_llsec_table,
 	.lock_llsec_table = ieee802154_lock_llsec_table,
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 40195e2a6f1e..f7562f4cacdf 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -48,6 +48,15 @@ struct ieee802154_local {
 
 	struct hrtimer ifs_timer;
 
+	/* Scanning */
+	struct mutex scan_lock;
+	atomic_t scanning;
+	__le64 scan_addr;
+	int scan_channel_idx;
+	struct cfg802154_scan_request __rcu *scan_req;
+	struct ieee802154_sub_if_data __rcu *scan_sdata;
+	struct delayed_work scan_work;
+
 	bool started;
 	bool suspended;
 
@@ -197,6 +206,19 @@ static inline bool mac802154_queue_is_stopped(struct ieee802154_local *local)
 	return atomic_read(&local->phy->hold_txs);
 }
 
+/* scanning handling */
+void mac802154_scan_work(struct work_struct *work);
+int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_scan_request *request);
+int mac802154_abort_scan_locked(struct ieee802154_local *local);
+int mac802154_scan_process_beacon(struct ieee802154_local *local,
+				  struct sk_buff *skb);
+
+static inline bool mac802154_scan_is_ongoing(struct ieee802154_local *local)
+{
+	return atomic_read(&local->scanning);
+}
+
 /* interface handling */
 int ieee802154_iface_init(void);
 void ieee802154_iface_exit(void);
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 43fd4cc13b66..bd453b1c0223 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -90,6 +90,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	INIT_LIST_HEAD(&local->interfaces);
 	mutex_init(&local->iflist_mtx);
+	mutex_init(&local->scan_lock);
 
 	tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
 
@@ -97,7 +98,6 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	INIT_WORK(&local->sync_tx_work, ieee802154_xmit_sync_worker);
 	INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_work);
-	INIT_DELAYED_WORK(&local->beacons_work, mac802154_beacons_work);
 
 	/* init supported flags with 802.15.4 default ranges */
 	phy->supported.max_minbe = 8;
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index b8ce84618a55..f2f3eca9bc20 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -94,10 +94,15 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 
 	switch (mac_cb(skb)->type) {
 	case IEEE802154_FC_TYPE_BEACON:
-	case IEEE802154_FC_TYPE_ACK:
+		if (mac802154_scan_is_ongoing(sdata->local)) {
+			rc = mac802154_scan_process_beacon(sdata->local, skb);
+			if (!rc)
+				goto success;
+		}
+		goto fail;
 	case IEEE802154_FC_TYPE_MAC_CMD:
+	case IEEE802154_FC_TYPE_ACK:
 		goto fail;
-
 	case IEEE802154_FC_TYPE_DATA:
 		return ieee802154_deliver_skb(skb);
 	default:
@@ -109,6 +114,10 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 fail:
 	kfree_skb(skb);
 	return NET_RX_DROP;
+
+success:
+	kfree_skb(skb);
+	return NET_RX_SUCCESS;
 }
 
 static void
@@ -268,10 +277,12 @@ void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb)
 
 	ieee802154_monitors_rx(local, skb);
 
-	/* Check if transceiver doesn't validate the checksum.
-	 * If not we validate the checksum here.
+	/* Check if the transceiver doesn't validate the checksum, or if the
+	 * check might have been disabled like during a scan. In these cases,
+	 * we validate the checksum here.
 	 */
-	if (local->hw.flags & IEEE802154_HW_RX_DROP_BAD_CKSUM) {
+	if (local->hw.flags & IEEE802154_HW_RX_DROP_BAD_CKSUM ||
+	    mac802154_scan_is_ongoing(local)) {
 		crc = crc_ccitt(0, skb->data, skb->len);
 		if (crc) {
 			rcu_read_unlock();
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
new file mode 100644
index 000000000000..3129cc95157a
--- /dev/null
+++ b/net/mac802154/scan.c
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IEEE 802.15.4 scanning management
+ *
+ * Copyright (C) Qorvo, 2021
+ * Authors:
+ *   - David Girault <david.girault@qorvo.com>
+ *   - Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/rtnetlink.h>
+#include <net/mac802154.h>
+
+#include "ieee802154_i.h"
+#include "driver-ops.h"
+#include "../ieee802154/nl802154.h"
+
+static bool mac802154_check_promiscuous(struct ieee802154_local *local)
+{
+	struct ieee802154_sub_if_data *sdata;
+	bool promiscuous_on = false;
+
+	/* Check if one subif is already in promiscuous mode. Since the list is
+	 * protected by its own mutex, take it here to ensure no modification
+	 * occurs during the check.
+	 */
+	mutex_lock(&local->iflist_mtx);
+	list_for_each_entry(sdata, &local->interfaces, list) {
+		if (ieee802154_sdata_running(sdata) &&
+		    sdata->wpan_dev.promiscuous_mode) {
+			/* At least one is in promiscuous mode */
+			promiscuous_on = true;
+			break;
+		}
+	}
+	mutex_unlock(&local->iflist_mtx);
+	return promiscuous_on;
+}
+
+static int mac802154_set_promiscuous_mode(struct ieee802154_local *local,
+					  bool state)
+{
+	bool promiscuous_on = mac802154_check_promiscuous(local);
+	int ret;
+
+	if ((state && promiscuous_on) || (!state && !promiscuous_on))
+		return 0;
+
+	ret = drv_set_promiscuous_mode(local, state);
+	if (ret)
+		pr_err("Failed to %s promiscuous mode for SW scanning",
+		       state ? "set" : "reset");
+
+	return ret;
+}
+
+static int mac802154_send_scan_done(struct ieee802154_local *local)
+{
+	struct cfg802154_registered_device *rdev;
+	struct cfg802154_scan_request *scan_req;
+	struct wpan_dev *wpan_dev;
+
+	scan_req = rcu_dereference_protected(local->scan_req,
+					     lockdep_is_held(&local->scan_lock));
+	rdev = wpan_phy_to_rdev(scan_req->wpan_phy);
+	wpan_dev = scan_req->wpan_dev;
+
+	return nl802154_send_scan_done(rdev, wpan_dev);
+}
+
+static int mac802154_end_of_scan(struct ieee802154_local *local)
+{
+	drv_set_channel(local, local->phy->current_page,
+			local->phy->current_channel);
+	ieee802154_configure_durations(local->phy);
+	atomic_dec(&local->phy->hold_txs);
+	atomic_set(&local->scanning, 0);
+	mac802154_set_promiscuous_mode(local, false);
+	ieee802154_wake_queue(&local->hw);
+
+	return mac802154_send_scan_done(local);
+}
+
+int mac802154_abort_scan_locked(struct ieee802154_local *local)
+{
+	lockdep_assert_held(&local->scan_lock);
+
+	if (!mac802154_scan_is_ongoing(local))
+		return -ESRCH;
+
+	cancel_delayed_work(&local->scan_work);
+
+	return mac802154_end_of_scan(local);
+}
+
+static unsigned int mac802154_scan_get_channel_time(u8 duration_order,
+						    u8 symbol_duration)
+{
+	u64 base_super_frame_duration = (u64)symbol_duration *
+		IEEE802154_SUPERFRAME_PERIOD * IEEE802154_SLOT_PERIOD;
+
+	return usecs_to_jiffies(base_super_frame_duration *
+				(BIT(duration_order) + 1));
+}
+
+void mac802154_scan_work(struct work_struct *work)
+{
+	struct ieee802154_local *local =
+		container_of(work, struct ieee802154_local, scan_work.work);
+	struct cfg802154_scan_request *scan_req;
+	struct ieee802154_sub_if_data *sdata;
+	unsigned int scan_duration;
+	bool end_of_scan = false;
+	unsigned long chan;
+	int ret;
+
+	mutex_lock(&local->scan_lock);
+
+	if (!mac802154_scan_is_ongoing(local))
+		goto unlock_mutex;
+
+	sdata = rcu_dereference_protected(local->scan_sdata,
+					  lockdep_is_held(&local->scan_lock));
+	scan_req = rcu_dereference_protected(local->scan_req,
+					     lockdep_is_held(&local->scan_lock));
+
+	if (local->suspended || !ieee802154_sdata_running(sdata))
+		goto queue_work;
+
+	do {
+		chan = find_next_bit((const unsigned long *)&scan_req->channels,
+				     IEEE802154_MAX_CHANNEL + 1,
+				     local->scan_channel_idx + 1);
+
+		/* If there are no more channels left, complete the scan */
+		if (chan > IEEE802154_MAX_CHANNEL) {
+			end_of_scan = true;
+			goto unlock_mutex;
+		}
+
+		/* Channel switch cannot be made atomic so hide the chan number
+		 * in order to prevent beacon processing during this timeframe.
+		 */
+		local->scan_channel_idx = -1;
+		/* Bypass the stack on purpose */
+		ret = drv_set_channel(local, scan_req->page, chan);
+		local->scan_channel_idx = chan;
+		ieee802154_configure_durations(local->phy);
+	} while (ret);
+
+queue_work:
+	scan_duration = mac802154_scan_get_channel_time(scan_req->duration,
+							local->phy->symbol_duration);
+	pr_debug("Scan channel %lu of page %u for %ums\n",
+		 chan, scan_req->page, jiffies_to_msecs(scan_duration));
+	ieee802154_queue_delayed_work(&local->hw, &local->scan_work,
+				      scan_duration);
+
+unlock_mutex:
+	if (end_of_scan)
+		mac802154_end_of_scan(local);
+
+	mutex_unlock(&local->scan_lock);
+}
+
+int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_scan_request *request)
+{
+	struct ieee802154_local *local = sdata->local;
+	int ret;
+
+	lockdep_assert_held(&local->scan_lock);
+
+	if (mac802154_scan_is_ongoing(local))
+		return -EBUSY;
+
+	/* TODO: support other scanning type */
+	if (request->type != NL802154_SCAN_PASSIVE)
+		return -EOPNOTSUPP;
+
+	/* Store scanning parameters */
+	rcu_assign_pointer(local->scan_req, request);
+	rcu_assign_pointer(local->scan_sdata, sdata);
+
+	/* Configure scan_addr to use net_device addr or random */
+	if (request->flags & NL802154_SCAN_FLAG_RANDOM_ADDR)
+		get_random_bytes(&local->scan_addr, sizeof(local->scan_addr));
+	else
+		local->scan_addr = cpu_to_le64(get_unaligned_be64(sdata->dev->dev_addr));
+
+	local->scan_channel_idx = -1;
+	atomic_set(&local->scanning, 1);
+
+	/* Software scanning requires to set promiscuous mode, so we need to
+	 * pause the Tx queue
+	 */
+	atomic_inc(&local->phy->hold_txs);
+	ieee802154_stop_queue(&local->hw);
+	ieee802154_sync_tx(local);
+
+	ret = mac802154_set_promiscuous_mode(local, true);
+	if (ret)
+		return mac802154_end_of_scan(local);
+
+	ieee802154_queue_delayed_work(&local->hw, &local->scan_work, 0);
+
+	return 0;
+}
+
+int mac802154_scan_process_beacon(struct ieee802154_local *local,
+				  struct sk_buff *skb)
+{
+	struct ieee802154_beacon_hdr *bh = (void *)skb->data;
+	struct ieee802154_addr *src = &mac_cb(skb)->source;
+	struct cfg802154_scan_request *scan_req;
+	struct ieee802154_pan_desc desc = {};
+	int ret;
+
+	/* Check the validity of the frame length */
+	if (skb->len < sizeof(*bh))
+		return -EINVAL;
+
+	if (unlikely(src->mode == IEEE802154_ADDR_NONE))
+		return -EINVAL;
+
+	if (unlikely(!bh->pan_coordinator))
+		return -ENODEV;
+
+	scan_req = rcu_dereference(local->scan_req);
+	if (unlikely(!scan_req))
+		return -EINVAL;
+
+	if (unlikely(local->scan_channel_idx < 0)) {
+		pr_info("Dropping beacon received during channel change\n");
+		return 0;
+	}
+
+	pr_debug("Beacon received on channel %d of page %d\n",
+		 local->scan_channel_idx, scan_req->page);
+
+	/* Parse beacon and create PAN information */
+	desc.coord = src;
+	desc.page = scan_req->page;
+	desc.channel = local->scan_channel_idx;
+	desc.link_quality = mac_cb(skb)->lqi;
+	desc.superframe_spec = get_unaligned_le16(skb->data);
+	desc.gts_permit = bh->gts_permit;
+
+	/* Create or update the PAN entry in the management layer */
+	ret = cfg802154_record_pan(local->phy, &desc);
+	if (ret) {
+		pr_err("Failed to save PAN descriptor\n");
+		return ret;
+	}
+
+	return 0;
+}
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 334843f66ec4..1849e5cb5945 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -58,6 +58,9 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 	struct net_device *dev = skb->dev;
 	int ret;
 
+	if (unlikely(mac802154_scan_is_ongoing(local)))
+		return NETDEV_TX_BUSY;
+
 	if (!(local->hw.flags & IEEE802154_HW_TX_OMIT_CKSUM)) {
 		struct sk_buff *nskb;
 		u16 crc;
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
index 230fe3390df7..5642a45df548 100644
--- a/net/mac802154/util.c
+++ b/net/mac802154/util.c
@@ -100,3 +100,29 @@ void ieee802154_stop_device(struct ieee802154_local *local)
 	hrtimer_cancel(&local->ifs_timer);
 	drv_stop(local);
 }
+
+/* Nothing should have been stuffed into the workqueue during
+ * the suspend->resume cycle.
+ */
+static bool ieee802154_can_queue_work(struct ieee802154_local *local)
+{
+	if (local->suspended) {
+		pr_warn("queueing ieee802154 work while suspended\n");
+		return false;
+	}
+
+	return true;
+}
+
+void ieee802154_queue_delayed_work(struct ieee802154_hw *hw,
+				   struct delayed_work *dwork,
+				   unsigned long delay)
+{
+	struct ieee802154_local *local = hw_to_local(hw);
+
+	if (!ieee802154_can_queue_work(local))
+		return;
+
+	queue_delayed_work(local->workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(ieee802154_queue_delayed_work);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 34/41] net: ieee802154: Full PAN management
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (32 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 33/41] net: mac802154: Handle scan requests Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 35/41] net: ieee802154: Add beacons support Miquel Raynal
                   ` (7 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Now that scanning is supported and PANs properly registered, give
certain rights to the user, such as listing asynchronously the listed
PANs as well as flushing the list.

The maximum number of PANs to list and their delay before expiration can
be configured. By default there is no limit. When these parameters are
set, PANs are automatically dropped from the list.

This change has the side effect of moving the following helpers out of
the experimental zone as they are now used by non-experimental security
functions:
- nl802154_prepare_wpan_dev_dump()
- nl802154_finish_wpan_dev_dump()

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/nl802154.h    |  47 +++++++++
 net/ieee802154/nl802154.c | 197 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 242 insertions(+), 2 deletions(-)

diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 51eca3a2b14e..22af514dd339 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -61,6 +61,10 @@ enum nl802154_commands {
 	NL802154_CMD_TRIGGER_SCAN,
 	NL802154_CMD_ABORT_SCAN,
 	NL802154_CMD_SCAN_DONE,
+	NL802154_CMD_DUMP_PANS,
+	NL802154_CMD_FLUSH_PANS,
+	NL802154_CMD_SET_MAX_PAN_ENTRIES,
+	NL802154_CMD_SET_PANS_EXPIRATION,
 
 	/* add new commands above here */
 
@@ -141,6 +145,9 @@ enum nl802154_attrs {
 	NL802154_ATTR_SCAN_FLAGS,
 	NL802154_ATTR_SCAN_CHANNELS,
 	NL802154_ATTR_SCAN_DURATION,
+	NL802154_ATTR_PAN,
+	NL802154_ATTR_MAX_PAN_ENTRIES,
+	NL802154_ATTR_PANS_EXPIRATION,
 
 	/* add attributes here, update the policy in nl802154.c */
 
@@ -267,6 +274,46 @@ enum nl802154_scan_flags {
 	NL802154_SCAN_FLAG_RANDOM_ADDR = BIT(0),
 };
 
+/**
+ * enum nl802154_pan - Netlink attributes for a PAN
+ *
+ * @__NL802154_PAN_INVALID: invalid
+ * @NL802154_PAN_PANID: PANID of the PAN (2 bytes)
+ * @NL802154_PAN_COORD_ADDR: Coordinator address, (8 bytes or 2 bytes)
+ * @NL802154_PAN_CHANNEL: channel number, related to @NL802154_PAN_PAGE (u8)
+ * @NL802154_PAN_PAGE: channel page, related to @NL802154_PAN_CHANNEL (u8)
+ * @NL802154_PAN_PREAMBLE_CODE: Preamble code while the beacon was received,
+ *	this is PHY dependent and optional (4 bytes)
+ * @NL802154_PAN_SUPERFRAME_SPEC: superframe specification of the PAN (u16)
+ * @NL802154_PAN_LINK_QUALITY: signal quality of beacon in unspecified units,
+ *	scaled to 0..255 (u8)
+ * @NL802154_PAN_GTS_PERMIT: set to true if GTS is permitted on this PAN
+ * @NL802154_PAN_PAYLOAD_DATA: binary data containing the raw data from the
+ *	frame payload, (only if beacon or probe response had data)
+ * @NL802154_PAN_STATUS: status, if this PAN is "used"
+ * @NL802154_PAN_SEEN_MS_AGO: age of this PAN entry in ms
+ * @NL802154_PAN_PAD: attribute used for padding for 64-bit alignment
+ * @NL802154_PAN_MAX: highest PAN attribute
+ */
+enum nl802154_pan {
+	__NL802154_PAN_INVALID,
+	NL802154_PAN_PANID,
+	NL802154_PAN_COORD_ADDR,
+	NL802154_PAN_CHANNEL,
+	NL802154_PAN_PAGE,
+	NL802154_PAN_PREAMBLE_CODE,
+	NL802154_PAN_SUPERFRAME_SPEC,
+	NL802154_PAN_LINK_QUALITY,
+	NL802154_PAN_GTS_PERMIT,
+	NL802154_PAN_PAYLOAD_DATA,
+	NL802154_PAN_STATUS,
+	NL802154_PAN_SEEN_MS_AGO,
+	NL802154_PAN_PAD,
+
+	/* keep last */
+	NL802154_PAN_MAX,
+};
+
 /**
  * enum nl802154_cca_modes - cca modes
  *
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 99cbad1f1381..07bac1ae2cd2 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -223,6 +223,9 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 	[NL802154_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
 	[NL802154_ATTR_SCAN_CHANNELS] = { .type = NLA_U32 },
 	[NL802154_ATTR_SCAN_DURATION] = { .type = NLA_U8 },
+	[NL802154_ATTR_PAN] = { .type = NLA_NESTED },
+	[NL802154_ATTR_MAX_PAN_ENTRIES] = { .type = NLA_U32 },
+	[NL802154_ATTR_PANS_EXPIRATION] = { .type = NLA_U32 },
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
@@ -237,7 +240,6 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 };
 
-#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static int
 nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
 			       struct netlink_callback *cb,
@@ -296,7 +298,6 @@ nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev)
 {
 	rtnl_unlock();
 }
-#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 
 /* message building helper */
 static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
@@ -1517,6 +1518,172 @@ static int nl802154_abort_scan(struct sk_buff *skb, struct genl_info *info)
 	return rdev_abort_scan(rdev, wpan_dev);
 }
 
+static int nl802154_send_pan_info(struct sk_buff *msg,
+				  struct netlink_callback *cb,
+				  u32 seq, int flags,
+				  struct cfg802154_registered_device *rdev,
+				  struct wpan_dev *wpan_dev,
+				  struct cfg802154_internal_pan *intpan)
+{
+	struct ieee802154_pan_desc *pan = &intpan->desc;
+	struct nlattr *nla;
+	void *hdr;
+
+	ASSERT_RTNL();
+
+	hdr = nl802154hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
+			      NL802154_CMD_SCAN_DONE);
+	if (!hdr)
+		return -ENOBUFS;
+
+	genl_dump_check_consistent(cb, hdr);
+
+	if (nla_put_u32(msg, NL802154_ATTR_GENERATION, rdev->pan_generation))
+		goto nla_put_failure;
+
+	if (wpan_dev->netdev &&
+	    nla_put_u32(msg, NL802154_ATTR_IFINDEX, wpan_dev->netdev->ifindex))
+		goto nla_put_failure;
+
+	if (nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev),
+			      NL802154_ATTR_PAD))
+		goto nla_put_failure;
+
+	nla = nla_nest_start_noflag(msg, NL802154_ATTR_PAN);
+	if (!nla)
+		goto nla_put_failure;
+
+	if (nla_put(msg, NL802154_PAN_PANID, IEEE802154_PAN_ID_LEN,
+		    &pan->coord->pan_id))
+		goto nla_put_failure;
+
+	if (pan->coord->mode == IEEE802154_ADDR_SHORT) {
+		if (nla_put(msg, NL802154_PAN_COORD_ADDR,
+			    IEEE802154_SHORT_ADDR_LEN,
+			    &pan->coord->short_addr))
+			goto nla_put_failure;
+	} else {
+		if (nla_put(msg, NL802154_PAN_COORD_ADDR,
+			    IEEE802154_EXTENDED_ADDR_LEN,
+			    &pan->coord->extended_addr))
+			goto nla_put_failure;
+	}
+
+	if (nla_put_u8(msg, NL802154_PAN_CHANNEL, pan->channel))
+		goto nla_put_failure;
+
+	if (nla_put_u8(msg, NL802154_PAN_PAGE, pan->page))
+		goto nla_put_failure;
+
+	if (nla_put_u16(msg, NL802154_PAN_SUPERFRAME_SPEC,
+			pan->superframe_spec))
+		goto nla_put_failure;
+
+	if (nla_put_u8(msg, NL802154_PAN_LINK_QUALITY, pan->link_quality))
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL802154_PAN_SEEN_MS_AGO,
+			jiffies_to_msecs(jiffies - intpan->discovery_ts)))
+		goto nla_put_failure;
+
+	if (pan->gts_permit && nla_put_flag(msg, NL802154_PAN_GTS_PERMIT))
+		goto nla_put_failure;
+
+	/* TODO: NL802154_PAN_PAYLOAD_DATA if any */
+
+	nla_nest_end(msg, nla);
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int nl802154_dump_pans(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct cfg802154_registered_device *rdev;
+	struct cfg802154_internal_pan *pan;
+	struct wpan_dev *wpan_dev;
+	int err;
+
+	err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
+	if (err)
+		return err;
+
+	spin_lock_bh(&rdev->pan_lock);
+
+	if (cb->args[2])
+		goto out;
+
+	cb->seq = rdev->pan_generation;
+
+	ieee802154_for_each_pan(pan, rdev) {
+		err = nl802154_send_pan_info(skb, cb, cb->nlh->nlmsg_seq,
+					     NLM_F_MULTI, rdev, wpan_dev, pan);
+		if (err < 0)
+			goto out_err;
+	}
+
+	cb->args[2] = 1;
+out:
+	err = skb->len;
+out_err:
+	spin_unlock_bh(&rdev->pan_lock);
+
+	nl802154_finish_wpan_dev_dump(rdev);
+
+	return err;
+}
+
+static int nl802154_flush_pans(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+
+	spin_lock_bh(&rdev->pan_lock);
+	cfg802154_flush_pans(rdev);
+	spin_unlock_bh(&rdev->pan_lock);
+
+	return 0;
+}
+
+static int nl802154_set_max_pan_entries(struct sk_buff *skb,
+					struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	unsigned int max_entries;
+
+	if (!info->attrs[NL802154_ATTR_MAX_PAN_ENTRIES])
+		return -EINVAL;
+
+	max_entries = nla_get_u32(info->attrs[NL802154_ATTR_MAX_PAN_ENTRIES]);
+
+	spin_lock_bh(&rdev->pan_lock);
+	cfg802154_set_max_pan_entries(rdev, max_entries);
+	spin_unlock_bh(&rdev->pan_lock);
+
+	return 0;
+}
+
+static int nl802154_set_pans_expiration(struct sk_buff *skb,
+					struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	unsigned int exp_time_s;
+
+	if (!info->attrs[NL802154_ATTR_PANS_EXPIRATION])
+		return -EINVAL;
+
+	exp_time_s = nla_get_u32(info->attrs[NL802154_ATTR_PANS_EXPIRATION]);
+
+	spin_lock_bh(&rdev->pan_lock);
+	cfg802154_set_pans_expiration(rdev, exp_time_s);
+	spin_unlock_bh(&rdev->pan_lock);
+
+	return 0;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
 	[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
@@ -2621,6 +2788,32 @@ static const struct genl_ops nl802154_ops[] = {
 				  NL802154_FLAG_CHECK_NETDEV_UP |
 				  NL802154_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL802154_CMD_DUMP_PANS,
+		.dumpit = nl802154_dump_pans,
+		/* can be retrieved by unprivileged users */
+	},
+	{
+		.cmd = NL802154_CMD_FLUSH_PANS,
+		.doit = nl802154_flush_pans,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL802154_CMD_SET_MAX_PAN_ENTRIES,
+		.doit = nl802154_set_max_pan_entries,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL802154_CMD_SET_PANS_EXPIRATION,
+		.doit = nl802154_set_pans_expiration,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_NEED_RTNL,
+	},
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	{
 		.cmd = NL802154_CMD_SET_SEC_PARAMS,
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 35/41] net: ieee802154: Add beacons support
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (33 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 34/41] net: ieee802154: Full PAN management Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 36/41] net: mac802154: Handle beacons requests Miquel Raynal
                   ` (6 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This involves processing beacons requests from userspace: starting or
stopping the flow of beacons sent passively (for now) on a specific
interface. The page and channel must be changed beforehands if
needed. Interval orders above 14 are reserved to tell a device it must
answer BEACON_REQ coming from an active scan procedure (this is not
supported yet).

A netlink beacons request structure is created to list the
requirements.

Mac layers may now implement the ->send_beacons() and
->stop_beacons() hooks.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h   | 22 +++++++++++
 include/net/nl802154.h    |  3 ++
 net/ieee802154/nl802154.c | 81 +++++++++++++++++++++++++++++++++++++++
 net/ieee802154/rdev-ops.h | 24 ++++++++++++
 net/ieee802154/trace.h    | 21 ++++++++++
 5 files changed, 151 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 15b9cb2c213a..57bbc7eb22df 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -88,6 +88,24 @@ struct cfg802154_scan_request {
 	struct wpan_phy *wpan_phy;
 };
 
+/**
+ * struct cfg802154_beacons_request - beacons request descriptor
+ *
+ * @interval: interval n between sendings, in multiple order of the super frame
+ *            duration: aBaseSuperframeDuration * (2^n) unless the interval
+ *            order is greater or equal to 15, in this case beacons won't be
+ *            passively sent out at a fixed rate but instead inform the device
+ *            that it should answer beacon requests as part of active scan
+ *            procedures
+ * @wpan_dev: the concerned wpan device
+ * @wpan_phy: the wpan phy this was for
+ */
+struct cfg802154_beacons_request {
+	u8 interval;
+	struct wpan_dev *wpan_dev;
+	struct wpan_phy *wpan_phy;
+};
+
 struct cfg802154_ops {
 	struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
 							   const char *name,
@@ -130,6 +148,10 @@ struct cfg802154_ops {
 				struct cfg802154_scan_request *request);
 	int	(*abort_scan)(struct wpan_phy *wpan_phy,
 			      struct wpan_dev *wpan_dev);
+	int	(*send_beacons)(struct wpan_phy *wpan_phy,
+				struct cfg802154_beacons_request *request);
+	int	(*stop_beacons)(struct wpan_phy *wpan_phy,
+				struct wpan_dev *wpan_dev);
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	void	(*get_llsec_table)(struct wpan_phy *wpan_phy,
 				   struct wpan_dev *wpan_dev,
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 22af514dd339..20c46f15cef4 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -65,6 +65,8 @@ enum nl802154_commands {
 	NL802154_CMD_FLUSH_PANS,
 	NL802154_CMD_SET_MAX_PAN_ENTRIES,
 	NL802154_CMD_SET_PANS_EXPIRATION,
+	NL802154_CMD_SEND_BEACONS,
+	NL802154_CMD_STOP_BEACONS,
 
 	/* add new commands above here */
 
@@ -148,6 +150,7 @@ enum nl802154_attrs {
 	NL802154_ATTR_PAN,
 	NL802154_ATTR_MAX_PAN_ENTRIES,
 	NL802154_ATTR_PANS_EXPIRATION,
+	NL802154_ATTR_BEACON_INTERVAL,
 
 	/* add attributes here, update the policy in nl802154.c */
 
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 07bac1ae2cd2..1a0ce95625ec 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -226,6 +226,7 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 	[NL802154_ATTR_PAN] = { .type = NLA_NESTED },
 	[NL802154_ATTR_MAX_PAN_ENTRIES] = { .type = NLA_U32 },
 	[NL802154_ATTR_PANS_EXPIRATION] = { .type = NLA_U32 },
+	[NL802154_ATTR_BEACON_INTERVAL] = { .type = NLA_U8 },
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
@@ -1684,6 +1685,70 @@ static int nl802154_set_pans_expiration(struct sk_buff *skb,
 	return 0;
 }
 
+static int
+nl802154_send_beacons(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+	struct wpan_phy *wpan_phy = &rdev->wpan_phy;
+	struct cfg802154_beacons_request *request;
+	int err;
+
+	/* Avoid sending beacons on monitor interfaces */
+	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
+		return -EOPNOTSUPP;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	if (!request)
+		return -ENOMEM;
+
+	request->wpan_dev = wpan_dev;
+	request->wpan_phy = wpan_phy;
+
+	if (info->attrs[NL802154_ATTR_BEACON_INTERVAL]) {
+		request->interval = nla_get_u8(info->attrs[NL802154_ATTR_BEACON_INTERVAL]);
+		if (request->interval > IEEE802154_ACTIVE_SCAN_DURATION) {
+			pr_err("Interval is out of range\n");
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Use maximum duration order by default */
+		request->interval = IEEE802154_MAX_SCAN_DURATION;
+	}
+
+	err = rdev_send_beacons(rdev, request);
+	if (err) {
+		pr_err("Failure starting sending beacons (%d)\n", err);
+		goto free_request;
+	}
+
+	if (wpan_dev->netdev)
+		dev_hold(wpan_dev->netdev);
+
+free_request:
+	kfree(request);
+
+	return err;
+}
+
+static int
+nl802154_stop_beacons(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+	int err;
+
+	err = rdev_stop_beacons(rdev, wpan_dev);
+
+	if (err != -ESRCH && wpan_dev->netdev)
+		dev_put(wpan_dev->netdev);
+
+	return err;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
 	[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
@@ -2814,6 +2879,22 @@ static const struct genl_ops nl802154_ops[] = {
 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
 				  NL802154_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL802154_CMD_SEND_BEACONS,
+		.doit = nl802154_send_beacons,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_CHECK_NETDEV_UP |
+				  NL802154_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL802154_CMD_STOP_BEACONS,
+		.doit = nl802154_stop_beacons,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_CHECK_NETDEV_UP |
+				  NL802154_FLAG_NEED_RTNL,
+	},
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	{
 		.cmd = NL802154_CMD_SET_SEC_PARAMS,
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h
index e171d74c3251..fa85efeaa150 100644
--- a/net/ieee802154/rdev-ops.h
+++ b/net/ieee802154/rdev-ops.h
@@ -237,6 +237,30 @@ static inline int rdev_abort_scan(struct cfg802154_registered_device *rdev,
 	return ret;
 }
 
+static inline int rdev_send_beacons(struct cfg802154_registered_device *rdev,
+				    struct cfg802154_beacons_request *request)
+{
+	int ret;
+
+	/* TODO: check if this is an FFD? */
+
+	trace_802154_rdev_send_beacons(&rdev->wpan_phy, request);
+	ret = rdev->ops->send_beacons(&rdev->wpan_phy, request);
+	trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+	return ret;
+}
+
+static inline int rdev_stop_beacons(struct cfg802154_registered_device *rdev,
+				    struct wpan_dev *wpan_dev)
+{
+	int ret;
+
+	trace_802154_rdev_stop_beacons(&rdev->wpan_phy, wpan_dev);
+	ret = rdev->ops->stop_beacons(&rdev->wpan_phy, wpan_dev);
+	trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 /* TODO this is already a nl802154, so move into ieee802154 */
 static inline void
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h
index e5405f737ded..353ba799244f 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -315,6 +315,22 @@ TRACE_EVENT(802154_rdev_trigger_scan,
 		  WPAN_PHY_PR_ARG, __entry->page, __entry->channels, __entry->duration)
 );
 
+TRACE_EVENT(802154_rdev_send_beacons,
+	TP_PROTO(struct wpan_phy *wpan_phy,
+		 struct cfg802154_beacons_request *request),
+	TP_ARGS(wpan_phy, request),
+	TP_STRUCT__entry(
+		WPAN_PHY_ENTRY
+		__field(u8, interval)
+	),
+	TP_fast_assign(
+		WPAN_PHY_ASSIGN;
+		__entry->interval = request->interval;
+	),
+	TP_printk(WPAN_PHY_PR_FMT ", sending beacons (interval order: %d)",
+		  WPAN_PHY_PR_ARG, __entry->interval)
+);
+
 DECLARE_EVENT_CLASS(802154_wdev_template,
 	TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
 	TP_ARGS(wpan_phy, wpan_dev),
@@ -335,6 +351,11 @@ DEFINE_EVENT(802154_wdev_template, 802154_rdev_abort_scan,
 	TP_ARGS(wpan_phy, wpan_dev)
 );
 
+DEFINE_EVENT(802154_wdev_template, 802154_rdev_stop_beacons,
+	TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
+	TP_ARGS(wpan_phy, wpan_dev)
+);
+
 TRACE_EVENT(802154_rdev_return_int,
 	TP_PROTO(struct wpan_phy *wpan_phy, int ret),
 	TP_ARGS(wpan_phy, ret),
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 36/41] net: mac802154: Handle beacons requests
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (34 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 35/41] net: ieee802154: Add beacons support Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 37/41] net: ieee802154: Trace the registration of new PANs Miquel Raynal
                   ` (5 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Implement the core hooks in order to provide the softMAC layer support
for sending beacons. Besides being able to test the full passive
scanning procedure, this will also be used when defining PAN coordinator
status, in order to give a device the right to answer received
BEACON_REQ.

Changing the channels is prohibited while a beacon operation is
ongoing.

The implementation uses a workqueue triggered at a certain interval
depending on the symbol duration for the current channel and the
interval order provided.

Sending beacons in response to an active scan request is not
yet supported.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h |  24 ++++++
 net/ieee802154/header_ops.c     |  29 ++++++++
 net/mac802154/cfg.c             |  41 ++++++++++-
 net/mac802154/ieee802154_i.h    |  13 ++++
 net/mac802154/main.c            |   2 +
 net/mac802154/scan.c            | 126 ++++++++++++++++++++++++++++++++
 6 files changed, 233 insertions(+), 2 deletions(-)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 45dff5d11bc8..f7716aeec93b 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -116,6 +116,21 @@ enum ieee802154_frame_type {
 	IEEE802154_EXTENDED_FRAME,
 };
 
+enum ieee802154_frame_version {
+	IEEE802154_2003_STD,
+	IEEE802154_2006_STD,
+	IEEE802154_STD,
+	IEEE802154_RESERVED_STD,
+	IEEE802154_MULTIPURPOSE_STD = IEEE802154_2003_STD,
+};
+
+enum ieee802154_addressing_mode {
+	IEEE802154_NO_ADDRESSING,
+	IEEE802154_RESERVED,
+	IEEE802154_SHORT_ADDRESSING,
+	IEEE802154_EXTENDED_ADDRESSING,
+};
+
 struct ieee802154_hdr {
 	struct ieee802154_hdr_fc fc;
 	u8 seq;
@@ -124,6 +139,11 @@ struct ieee802154_hdr {
 	struct ieee802154_sechdr sec;
 };
 
+struct ieee802154_beacon_frame {
+	struct ieee802154_hdr mhr;
+	struct ieee802154_beacon_hdr mac_pl;
+};
+
 /* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
  * the contents of hdr will be, and the actual value of those bits in
  * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
@@ -149,6 +169,10 @@ int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
  */
 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
 
+/* pushes a beacon frame into an skb */
+int ieee802154_beacon_push(struct sk_buff *skb,
+			   struct ieee802154_beacon_frame *beacon);
+
 int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
 
 static inline int
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
index af337cf62764..bab710aa36f9 100644
--- a/net/ieee802154/header_ops.c
+++ b/net/ieee802154/header_ops.c
@@ -6,6 +6,7 @@
  * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
  */
 
+#include <linux/crc-ccitt.h>
 #include <linux/ieee802154.h>
 
 #include <net/mac802154.h>
@@ -120,6 +121,34 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
 }
 EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
 
+int ieee802154_beacon_push(struct sk_buff *skb,
+			   struct ieee802154_beacon_frame *beacon)
+{
+	struct ieee802154_beacon_hdr *mac_pl = &beacon->mac_pl;
+	struct ieee802154_hdr *mhr = &beacon->mhr;
+	u16 crc;
+	int ret;
+
+	skb_reserve(skb, sizeof(*mhr));
+	ret = ieee802154_hdr_push(skb, mhr);
+	if (ret < 0)
+		return ret;
+
+	skb_reset_mac_header(skb);
+	skb->mac_len = ret;
+
+	skb_put_data(skb, mac_pl, sizeof(*mac_pl));
+
+	if (mac_pl->pend_short_addr_count || mac_pl->pend_ext_addr_count)
+		return -EOPNOTSUPP;
+
+	crc = crc_ccitt(0, skb->data, skb->len);
+	put_unaligned_le16(crc, skb_put(skb, 2));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ieee802154_beacon_push);
+
 static int
 ieee802154_hdr_get_addr(const u8 *buf, int mode, bool omit_pan,
 			struct ieee802154_addr *addr)
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 958b609b8c1b..5a22297708ec 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -117,8 +117,10 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 	    wpan_phy->current_channel == channel)
 		return 0;
 
-	/* Refuse to change channels during a scanning operation */
-	if (mac802154_scan_is_ongoing(local))
+	/* Refuse to change channels during a scanning operation or when a
+	 * beacons request is ongoing.
+	 */
+	if (mac802154_scan_is_ongoing(local) || local->ongoing_beacons_request)
 		return -EBUSY;
 
 	ret = drv_set_channel(local, page, channel);
@@ -301,6 +303,39 @@ static int mac802154_abort_scan(struct wpan_phy *wpan_phy,
 	return ret;
 }
 
+static int mac802154_send_beacons(struct wpan_phy *wpan_phy,
+				  struct cfg802154_beacons_request *request)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	struct ieee802154_sub_if_data *sdata;
+	int ret;
+
+	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(request->wpan_dev);
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->beacons_lock);
+	ret = mac802154_send_beacons_locked(sdata, request);
+	mutex_unlock(&local->beacons_lock);
+
+	return ret;
+}
+
+static int mac802154_stop_beacons(struct wpan_phy *wpan_phy,
+				  struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	int ret;
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->beacons_lock);
+	ret = mac802154_stop_beacons_locked(local);
+	mutex_unlock(&local->beacons_lock);
+
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static void
 ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -510,6 +545,8 @@ const struct cfg802154_ops mac802154_config_ops = {
 	.set_ackreq_default = ieee802154_set_ackreq_default,
 	.trigger_scan = mac802154_trigger_scan,
 	.abort_scan = mac802154_abort_scan,
+	.send_beacons = mac802154_send_beacons,
+	.stop_beacons = mac802154_stop_beacons,
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	.get_llsec_table = ieee802154_get_llsec_table,
 	.lock_llsec_table = ieee802154_lock_llsec_table,
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index f7562f4cacdf..514446c1f815 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -57,6 +57,14 @@ struct ieee802154_local {
 	struct ieee802154_sub_if_data __rcu *scan_sdata;
 	struct delayed_work scan_work;
 
+	/* Beacons handling */
+	bool ongoing_beacons_request;
+	struct mutex beacons_lock;
+	unsigned int beacons_interval;
+	struct delayed_work beacons_work;
+	struct ieee802154_sub_if_data __rcu *beacons_sdata;
+	struct ieee802154_beacon_frame beacon;
+
 	bool started;
 	bool suspended;
 
@@ -219,6 +227,11 @@ static inline bool mac802154_scan_is_ongoing(struct ieee802154_local *local)
 	return atomic_read(&local->scanning);
 }
 
+void mac802154_beacons_work(struct work_struct *work);
+int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_beacons_request *request);
+int mac802154_stop_beacons_locked(struct ieee802154_local *local);
+
 /* interface handling */
 int ieee802154_iface_init(void);
 void ieee802154_iface_exit(void);
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index bd453b1c0223..8992bcc3eca9 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -91,6 +91,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 	INIT_LIST_HEAD(&local->interfaces);
 	mutex_init(&local->iflist_mtx);
 	mutex_init(&local->scan_lock);
+	mutex_init(&local->beacons_lock);
 
 	tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
 
@@ -98,6 +99,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	INIT_WORK(&local->sync_tx_work, ieee802154_xmit_sync_worker);
 	INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_work);
+	INIT_DELAYED_WORK(&local->beacons_work, mac802154_beacons_work);
 
 	/* init supported flags with 802.15.4 default ranges */
 	phy->supported.max_minbe = 8;
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index 3129cc95157a..d9b54b35660a 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -17,6 +17,13 @@
 #include "driver-ops.h"
 #include "../ieee802154/nl802154.h"
 
+#define IEEE802154_BEACON_MHR_SZ 13
+#define IEEE802154_BEACON_PL_SZ 4
+#define IEEE802154_CRC_SZ 2
+#define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \
+				  IEEE802154_BEACON_PL_SZ + \
+				  IEEE802154_CRC_SZ)
+
 static bool mac802154_check_promiscuous(struct ieee802154_local *local)
 {
 	struct ieee802154_sub_if_data *sdata;
@@ -257,3 +264,122 @@ int mac802154_scan_process_beacon(struct ieee802154_local *local,
 
 	return 0;
 }
+
+static int mac802154_transmit_beacon_locked(struct ieee802154_local *local,
+					    struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_sub_if_data *sdata;
+	struct sk_buff *skb;
+	int ret;
+
+	lockdep_assert_held(&local->beacons_lock);
+
+	/* Update the sequence number */
+	local->beacon.mhr.seq = atomic_inc_return(&wpan_dev->bsn);
+
+	skb = alloc_skb(IEEE802154_BEACON_SKB_SZ, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	sdata = rcu_dereference_protected(local->beacons_sdata,
+					  lockdep_is_held(&local->beacons_lock));
+	skb->dev = sdata->dev;
+
+	ret = ieee802154_beacon_push(skb, &local->beacon);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	ieee802154_mlme_tx(local, skb);
+
+	return 0;
+}
+
+void mac802154_beacons_work(struct work_struct *work)
+{
+	struct ieee802154_local *local =
+		container_of(work, struct ieee802154_local, beacons_work.work);
+	struct ieee802154_sub_if_data *sdata;
+	struct wpan_dev *wpan_dev;
+	int ret;
+
+	mutex_lock(&local->beacons_lock);
+
+	if (!local->ongoing_beacons_request)
+		goto unlock_mutex;
+
+	if (local->suspended)
+		goto queue_work;
+
+	sdata = rcu_dereference_protected(local->beacons_sdata,
+					  lockdep_is_held(&local->beacons_lock));
+	wpan_dev = &sdata->wpan_dev;
+
+	ret = mac802154_transmit_beacon_locked(local, wpan_dev);
+	if (ret)
+		pr_err("Error when transmitting beacon (%d)\n", ret);
+
+queue_work:
+	ieee802154_queue_delayed_work(&local->hw, &local->beacons_work,
+				      local->beacons_interval);
+
+unlock_mutex:
+	mutex_unlock(&local->beacons_lock);
+}
+
+int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_beacons_request *request)
+{
+	struct ieee802154_local *local = sdata->local;
+
+	lockdep_assert_held(&local->beacons_lock);
+
+	if (local->ongoing_beacons_request)
+		return -EBUSY;
+
+	local->ongoing_beacons_request = true;
+
+	memset(&local->beacon, 0, sizeof(local->beacon));
+	local->beacon.mhr.fc.type = IEEE802154_BEACON_FRAME;
+	local->beacon.mhr.fc.security_enabled = 0;
+	local->beacon.mhr.fc.frame_pending = 0;
+	local->beacon.mhr.fc.ack_request = 0;
+	local->beacon.mhr.fc.intra_pan = 0;
+	local->beacon.mhr.fc.dest_addr_mode = IEEE802154_NO_ADDRESSING;
+	local->beacon.mhr.fc.version = IEEE802154_2003_STD;
+	local->beacon.mhr.fc.source_addr_mode = IEEE802154_EXTENDED_ADDRESSING;
+	atomic_set(&request->wpan_dev->bsn, -1);
+	local->beacon.mhr.source.mode = IEEE802154_ADDR_LONG;
+	local->beacon.mhr.source.pan_id = cpu_to_le16(request->wpan_dev->pan_id);
+	local->beacon.mhr.source.extended_addr = cpu_to_le64(request->wpan_dev->extended_addr);
+	local->beacon.mac_pl.beacon_order = request->interval;
+	local->beacon.mac_pl.superframe_order = request->interval;
+	local->beacon.mac_pl.final_cap_slot = 0xf;
+	local->beacon.mac_pl.battery_life_ext = 0;
+	local->beacon.mac_pl.pan_coordinator = 1;
+	local->beacon.mac_pl.assoc_permit = 1;
+
+	rcu_assign_pointer(local->beacons_sdata, sdata);
+
+	/* Start the beacon work */
+	local->beacons_interval =
+		mac802154_scan_get_channel_time(request->interval,
+						request->wpan_phy->symbol_duration);
+	ieee802154_queue_delayed_work(&local->hw, &local->beacons_work, 0);
+
+	return 0;
+}
+
+int mac802154_stop_beacons_locked(struct ieee802154_local *local)
+{
+	lockdep_assert_held(&local->beacons_lock);
+
+	if (!local->ongoing_beacons_request)
+		return -ESRCH;
+
+	local->ongoing_beacons_request = false;
+	cancel_delayed_work(&local->beacons_work);
+
+	return 0;
+}
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 37/41] net: ieee802154: Trace the registration of new PANs
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (35 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 36/41] net: mac802154: Handle beacons requests Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 38/41] net: mac802154: Add support for active scans Miquel Raynal
                   ` (4 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

Add an internal trace when new PANs get discovered.

Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/ieee802154/pan.c   |  3 +++
 net/ieee802154/trace.h | 25 +++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
index 1ea15ea1b3bd..5afc0aa38a43 100644
--- a/net/ieee802154/pan.c
+++ b/net/ieee802154/pan.c
@@ -18,6 +18,7 @@
 
 #include "ieee802154.h"
 #include "core.h"
+#include "trace.h"
 
 static struct cfg802154_internal_pan *
 cfg802154_alloc_pan(struct ieee802154_pan_desc *desc)
@@ -205,6 +206,8 @@ static void cfg802154_pan_update(struct cfg802154_registered_device *rdev,
 	found = cfg802154_find_matching_pan(rdev, new);
 	if (found)
 		cfg802154_unlink_pan(rdev, found);
+	else
+		trace_802154_new_pan(&new->desc);
 
 	if (unlikely(cfg802154_need_to_expire_pans(rdev)))
 		cfg802154_expire_oldest_pan(rdev);
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h
index 353ba799244f..506fe4930440 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -356,6 +356,31 @@ DEFINE_EVENT(802154_wdev_template, 802154_rdev_stop_beacons,
 	TP_ARGS(wpan_phy, wpan_dev)
 );
 
+DECLARE_EVENT_CLASS(802154_pan_evt,
+	TP_PROTO(struct ieee802154_pan_desc *desc),
+	TP_ARGS(desc),
+	TP_STRUCT__entry(
+		__field(u16, pan_id)
+		__field(__le64, coord_addr)
+		__field(u8, channel)
+		__field(u8, page)
+	),
+	TP_fast_assign(
+		__entry->page = desc->page;
+		__entry->channel = desc->channel;
+		memcpy(&__entry->pan_id, &desc->coord->pan_id, 2);
+		memcpy(&__entry->coord_addr, &desc->coord->extended_addr, 8);
+	),
+	TP_printk("panid: %u, coord_addr: 0x%llx, page: %u, channel: %u",
+		  __entry->pan_id, __le64_to_cpu(__entry->coord_addr),
+		  __entry->page, __entry->channel)
+);
+
+DEFINE_EVENT(802154_pan_evt, 802154_new_pan,
+	TP_PROTO(struct ieee802154_pan_desc *desc),
+	TP_ARGS(desc)
+);
+
 TRACE_EVENT(802154_rdev_return_int,
 	TP_PROTO(struct wpan_phy *wpan_phy, int ret),
 	TP_ARGS(wpan_phy, ret),
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 38/41] net: mac802154: Add support for active scans
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (36 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 37/41] net: ieee802154: Trace the registration of new PANs Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 39/41] net: mac802154: Add support for processing beacon requests Miquel Raynal
                   ` (3 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Active scan support is based on the current passive scan support,
cheered up with beacon requests sent after every channel change.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h | 14 +++++++-
 net/ieee802154/header_ops.c     | 25 +++++++++++++++
 net/mac802154/ieee802154_i.h    |  1 +
 net/mac802154/scan.c            | 57 +++++++++++++++++++++++++++++++--
 4 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index f7716aeec93b..1bf1a4e508a2 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -58,6 +58,11 @@ struct ieee802154_beacon_hdr {
 #endif
 } __packed;
 
+struct ieee802154_mac_cmd_pl {
+	u8  cmd_id;
+	/* TODO: content depending on the cmd_id */
+} __packed;
+
 struct ieee802154_sechdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
 	u8 level:3,
@@ -139,6 +144,11 @@ struct ieee802154_hdr {
 	struct ieee802154_sechdr sec;
 };
 
+struct ieee802154_beacon_req_frame {
+	struct ieee802154_hdr mhr;
+	struct ieee802154_mac_cmd_pl mac_pl;
+};
+
 struct ieee802154_beacon_frame {
 	struct ieee802154_hdr mhr;
 	struct ieee802154_beacon_hdr mac_pl;
@@ -169,7 +179,9 @@ int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
  */
 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
 
-/* pushes a beacon frame into an skb */
+/* pushes a beacon_req or a beacon frame into an skb */
+int ieee802154_beacon_req_push(struct sk_buff *skb,
+			       struct ieee802154_beacon_req_frame *breq);
 int ieee802154_beacon_push(struct sk_buff *skb,
 			   struct ieee802154_beacon_frame *beacon);
 
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
index bab710aa36f9..c31a9e429a14 100644
--- a/net/ieee802154/header_ops.c
+++ b/net/ieee802154/header_ops.c
@@ -121,6 +121,31 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
 }
 EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
 
+int ieee802154_beacon_req_push(struct sk_buff *skb,
+			       struct ieee802154_beacon_req_frame *breq)
+{
+	struct ieee802154_mac_cmd_pl *mac_pl = &breq->mac_pl;
+	struct ieee802154_hdr *mhr = &breq->mhr;
+	u16 crc;
+	int ret;
+
+	skb_reserve(skb, sizeof(*mhr));
+	ret = ieee802154_hdr_push(skb, mhr);
+	if (ret < 0)
+		return ret;
+
+	skb_reset_mac_header(skb);
+	skb->mac_len = ret;
+
+	skb_put_data(skb, mac_pl, sizeof(*mac_pl));
+
+	crc = crc_ccitt(0, skb->data, skb->len);
+	put_unaligned_le16(crc, skb_put(skb, 2));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ieee802154_beacon_req_push);
+
 int ieee802154_beacon_push(struct sk_buff *skb,
 			   struct ieee802154_beacon_frame *beacon)
 {
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 514446c1f815..0b1bcbab1ff3 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -56,6 +56,7 @@ struct ieee802154_local {
 	struct cfg802154_scan_request __rcu *scan_req;
 	struct ieee802154_sub_if_data __rcu *scan_sdata;
 	struct delayed_work scan_work;
+	struct ieee802154_beacon_req_frame beacon_req;
 
 	/* Beacons handling */
 	bool ongoing_beacons_request;
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index d9b54b35660a..71a845e3e76d 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -19,10 +19,15 @@
 
 #define IEEE802154_BEACON_MHR_SZ 13
 #define IEEE802154_BEACON_PL_SZ 4
+#define IEEE802154_BEACON_REQ_MHR_SZ 7
+#define IEEE802154_BEACON_REQ_PL_SZ 1
 #define IEEE802154_CRC_SZ 2
 #define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \
 				  IEEE802154_BEACON_PL_SZ + \
 				  IEEE802154_CRC_SZ)
+#define IEEE802154_BEACON_REQ_SKB_SZ (IEEE802154_BEACON_REQ_MHR_SZ + \
+				      IEEE802154_BEACON_REQ_PL_SZ +  \
+				      IEEE802154_CRC_SZ)
 
 static bool mac802154_check_promiscuous(struct ieee802154_local *local)
 {
@@ -112,6 +117,48 @@ static unsigned int mac802154_scan_get_channel_time(u8 duration_order,
 				(BIT(duration_order) + 1));
 }
 
+static int mac802154_scan_prepare_beacon_req(struct ieee802154_local *local)
+{
+	memset(&local->beacon_req, 0, sizeof(local->beacon_req));
+	local->beacon_req.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
+	local->beacon_req.mhr.fc.dest_addr_mode = IEEE802154_SHORT_ADDRESSING;
+	local->beacon_req.mhr.fc.version = IEEE802154_2003_STD;
+	local->beacon_req.mhr.fc.source_addr_mode = IEEE802154_NO_ADDRESSING;
+	local->beacon_req.mhr.dest.mode = IEEE802154_ADDR_SHORT;
+	local->beacon_req.mhr.dest.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
+	local->beacon_req.mhr.dest.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
+	local->beacon_req.mac_pl.cmd_id = IEEE802154_CMD_BEACON_REQ;
+
+	return 0;
+}
+
+static int mac802154_transmit_beacon_req_locked(struct ieee802154_local *local)
+{
+	struct ieee802154_sub_if_data *sdata;
+	struct sk_buff *skb;
+	int ret;
+
+	lockdep_assert_held(&local->scan_lock);
+
+	skb = alloc_skb(IEEE802154_BEACON_REQ_SKB_SZ, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	sdata = rcu_dereference_protected(local->scan_sdata,
+					  lockdep_is_held(&local->scan_lock));
+	skb->dev = sdata->dev;
+
+	ret = ieee802154_beacon_req_push(skb, &local->beacon_req);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	ieee802154_mlme_tx(local, skb);
+
+	return 0;
+}
+
 void mac802154_scan_work(struct work_struct *work)
 {
 	struct ieee802154_local *local =
@@ -157,6 +204,9 @@ void mac802154_scan_work(struct work_struct *work)
 		ieee802154_configure_durations(local->phy);
 	} while (ret);
 
+	if (scan_req->type == NL802154_SCAN_ACTIVE)
+		mac802154_transmit_beacon_req_locked(local);
+
 queue_work:
 	scan_duration = mac802154_scan_get_channel_time(scan_req->duration,
 							local->phy->symbol_duration);
@@ -183,8 +233,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
 	if (mac802154_scan_is_ongoing(local))
 		return -EBUSY;
 
-	/* TODO: support other scanning type */
-	if (request->type != NL802154_SCAN_PASSIVE)
+	if (request->type != NL802154_SCAN_PASSIVE &&
+	    request->type != NL802154_SCAN_ACTIVE)
 		return -EOPNOTSUPP;
 
 	/* Store scanning parameters */
@@ -197,6 +247,9 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
 	else
 		local->scan_addr = cpu_to_le64(get_unaligned_be64(sdata->dev->dev_addr));
 
+	if (request->type == NL802154_SCAN_ACTIVE)
+		mac802154_scan_prepare_beacon_req(local);
+
 	local->scan_channel_idx = -1;
 	atomic_set(&local->scanning, 1);
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 39/41] net: mac802154: Add support for processing beacon requests
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (37 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 38/41] net: mac802154: Add support for active scans Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 40/41] net: ieee802154: Handle limited devices with only datagram support Miquel Raynal
                   ` (2 subsequent siblings)
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

When performing an active scan, coordinators emit beacon requests which
must be answered by other PANs receiving the request.

Answering a beacon request is considered a duty whenever the user
performs a "send beacons" command with an interval of 15. As in the
softMAC we save the interval in micro-seconds, we use a negative value
to discriminate between a passive beacons command and the task to answer
received beacon requests.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h |  4 +++-
 net/ieee802154/header_ops.c     | 13 +++++++++++++
 net/mac802154/ieee802154_i.h    | 17 ++++++++++++++++-
 net/mac802154/rx.c              | 13 +++++++++++++
 net/mac802154/scan.c            | 17 +++++++++++++----
 5 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 1bf1a4e508a2..a2dba4442c57 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -179,9 +179,11 @@ int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
  */
 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
 
-/* pushes a beacon_req or a beacon frame into an skb */
+/* pushes/pulls a beacon_req or a beacon frame into/from an skb */
 int ieee802154_beacon_req_push(struct sk_buff *skb,
 			       struct ieee802154_beacon_req_frame *breq);
+int ieee802154_beacon_req_pl_pull(struct sk_buff *skb,
+				  struct ieee802154_mac_cmd_pl *mac_pl);
 int ieee802154_beacon_push(struct sk_buff *skb,
 			   struct ieee802154_beacon_frame *beacon);
 
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
index c31a9e429a14..771dbcf6e0b8 100644
--- a/net/ieee802154/header_ops.c
+++ b/net/ieee802154/header_ops.c
@@ -314,6 +314,19 @@ ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr)
 }
 EXPORT_SYMBOL_GPL(ieee802154_hdr_pull);
 
+int ieee802154_beacon_req_pl_pull(struct sk_buff *skb,
+				  struct ieee802154_mac_cmd_pl *mac_pl)
+{
+	if (!pskb_may_pull(skb, sizeof(*mac_pl)))
+		return -EINVAL;
+
+	memcpy(mac_pl, skb->data, sizeof(*mac_pl));
+	skb_pull(skb, sizeof(*mac_pl));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ieee802154_beacon_req_pl_pull);
+
 int
 ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr)
 {
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 0b1bcbab1ff3..1e394b59d983 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -61,7 +61,7 @@ struct ieee802154_local {
 	/* Beacons handling */
 	bool ongoing_beacons_request;
 	struct mutex beacons_lock;
-	unsigned int beacons_interval;
+	int beacons_interval;
 	struct delayed_work beacons_work;
 	struct ieee802154_sub_if_data __rcu *beacons_sdata;
 	struct ieee802154_beacon_frame beacon;
@@ -136,6 +136,21 @@ ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata)
 	return test_bit(SDATA_STATE_RUNNING, &sdata->state);
 }
 
+static inline bool ieee802154_frame_is_beacon_req(struct sk_buff *skb)
+{
+	struct ieee802154_mac_cmd_pl mac_pl;
+	int ret;
+
+	if (mac_cb(skb)->type != IEEE802154_FC_TYPE_MAC_CMD)
+		return false;
+
+	ret = ieee802154_beacon_req_pl_pull(skb, &mac_pl);
+	if (ret)
+		return false;
+
+	return mac_pl.cmd_id == IEEE802154_CMD_BEACON_REQ;
+}
+
 extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
 
 void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index f2f3eca9bc20..1aba23d007cf 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -29,6 +29,11 @@ static int ieee802154_deliver_skb(struct sk_buff *skb)
 	return netif_receive_skb(skb);
 }
 
+static bool mac802154_should_answer_beacon_req(struct ieee802154_local *local)
+{
+	return local->ongoing_beacons_request && local->beacons_interval < 0;
+}
+
 static int
 ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 		       struct sk_buff *skb, const struct ieee802154_hdr *hdr)
@@ -101,6 +106,14 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 		}
 		goto fail;
 	case IEEE802154_FC_TYPE_MAC_CMD:
+		if (ieee802154_frame_is_beacon_req(skb) &&
+		    mac802154_should_answer_beacon_req(sdata->local)) {
+			ieee802154_queue_delayed_work(&sdata->local->hw,
+						      &sdata->local->beacons_work,
+						      0);
+			goto success;
+		}
+		goto fail;
 	case IEEE802154_FC_TYPE_ACK:
 		goto fail;
 	case IEEE802154_FC_TYPE_DATA:
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index 71a845e3e76d..767fc2ac8109 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -374,8 +374,9 @@ void mac802154_beacons_work(struct work_struct *work)
 		pr_err("Error when transmitting beacon (%d)\n", ret);
 
 queue_work:
-	ieee802154_queue_delayed_work(&local->hw, &local->beacons_work,
-				      local->beacons_interval);
+	if (local->beacons_interval >= 0)
+		ieee802154_queue_delayed_work(&local->hw, &local->beacons_work,
+					      local->beacons_interval);
 
 unlock_mutex:
 	mutex_unlock(&local->beacons_lock);
@@ -407,7 +408,8 @@ int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
 	local->beacon.mhr.source.pan_id = cpu_to_le16(request->wpan_dev->pan_id);
 	local->beacon.mhr.source.extended_addr = cpu_to_le64(request->wpan_dev->extended_addr);
 	local->beacon.mac_pl.beacon_order = request->interval;
-	local->beacon.mac_pl.superframe_order = request->interval;
+	if (request->interval <= IEEE802154_MAX_SCAN_DURATION)
+		local->beacon.mac_pl.superframe_order = request->interval;
 	local->beacon.mac_pl.final_cap_slot = 0xf;
 	local->beacon.mac_pl.battery_life_ext = 0;
 	local->beacon.mac_pl.pan_coordinator = 1;
@@ -415,6 +417,11 @@ int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
 
 	rcu_assign_pointer(local->beacons_sdata, sdata);
 
+	if (request->interval == IEEE802154_ACTIVE_SCAN_DURATION) {
+		local->beacons_interval = -1;
+		return 0;
+	}
+
 	/* Start the beacon work */
 	local->beacons_interval =
 		mac802154_scan_get_channel_time(request->interval,
@@ -432,7 +439,9 @@ int mac802154_stop_beacons_locked(struct ieee802154_local *local)
 		return -ESRCH;
 
 	local->ongoing_beacons_request = false;
-	cancel_delayed_work(&local->beacons_work);
+
+	if (local->beacons_interval >= 0)
+		cancel_delayed_work(&local->beacons_work);
 
 	return 0;
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 40/41] net: ieee802154: Handle limited devices with only datagram support
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (38 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 39/41] net: mac802154: Add support for processing beacon requests Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 11:54 ` [PATCH v3 41/41] net: ieee802154: ca8210: Flag the driver as being limited Miquel Raynal
  2022-01-17 23:02 ` [PATCH v3 00/41] IEEE 802.15.4 scan support Alexander Aring
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

Some devices, like hardMAC ones can be a bit limited in the way they
handle mac commands. In particular, they might just not support it at
all and instead only be able to transmit and receive regular data
packets. In this case, they cannot be used for any of the internal
management commands that we have introduced so far and must be flagged
accordingly.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h   | 3 +++
 net/ieee802154/nl802154.c | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 57bbc7eb22df..98a202e0e626 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -301,11 +301,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_DATAGRAMS_ONLY: Indicates that transceiver is only able to
+ *	send/receive datagrams.
  */
 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_DATAGRAMS_ONLY	= BIT(4),
 };
 
 struct wpan_phy {
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 1a0ce95625ec..443e5aba1aa9 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -1323,6 +1323,9 @@ static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
 		return -EOPNOTSUPP;
 
+	if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY)
+		return -EOPNOTSUPP;
+
 	request = kzalloc(sizeof(*request), GFP_KERNEL);
 	if (!request)
 		return -ENOMEM;
@@ -1699,6 +1702,9 @@ nl802154_send_beacons(struct sk_buff *skb, struct genl_info *info)
 	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
 		return -EOPNOTSUPP;
 
+	if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY)
+		return -EOPNOTSUPP;
+
 	request = kzalloc(sizeof(*request), GFP_KERNEL);
 	if (!request)
 		return -ENOMEM;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v3 41/41] net: ieee802154: ca8210: Flag the driver as being limited
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (39 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 40/41] net: ieee802154: Handle limited devices with only datagram support Miquel Raynal
@ 2022-01-17 11:54 ` Miquel Raynal
  2022-01-17 23:02 ` [PATCH v3 00/41] IEEE 802.15.4 scan support Alexander Aring
  41 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-17 11:54 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: netdev, linux-wireless, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Michael Hennerich,
	Jakub Kicinski, Varka Bhadram, Xue Liu, Alan Ott,
	Thomas Petazzoni, Miquel Raynal

This is a hardMAC device wired to Linux 802154 softMAC
implementation. It is a bit limited in the sense that it cannot handle
anything else that datagrams. Let's flag it like this to prevent using
unsupported features such as scan/beacons handling.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/ca8210.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 374827f51dff..d1965be08a42 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2987,7 +2987,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
 	ca8210_hw->phy->flags =
 		WPAN_PHY_FLAG_TXPOWER |
 		WPAN_PHY_FLAG_CCA_ED_LEVEL |
-		WPAN_PHY_FLAG_CCA_MODE;
+		WPAN_PHY_FLAG_CCA_MODE |
+		WPAN_PHY_FLAG_DATAGRAMS_ONLY;
 }
 
 /**
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism
  2022-01-17 11:54 ` [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism Miquel Raynal
@ 2022-01-17 22:43   ` Alexander Aring
  2022-01-18 18:14     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-17 22:43 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
...
>
>         /* stop hardware - this must stop RX */
> diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
> index 0291e49058f2..37d5438fdb3f 100644
> --- a/net/mac802154/ieee802154_i.h
> +++ b/net/mac802154/ieee802154_i.h
> @@ -122,6 +122,7 @@ extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
>
>  void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
>  void ieee802154_xmit_sync_worker(struct work_struct *work);
> +void ieee802154_sync_tx(struct ieee802154_local *local);
>  netdev_tx_t
>  ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
>  netdev_tx_t
> diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
> index de5ecda80472..d1fd2cc67cbe 100644
> --- a/net/mac802154/tx.c
> +++ b/net/mac802154/tx.c
> @@ -48,6 +48,7 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
>
>         kfree_skb(skb);
>         atomic_dec(&local->phy->ongoing_txs);
> +       wake_up(&local->phy->sync_txq);

if (atomic_dec_and_test(&hw->phy->ongoing_txs))
      wake_up(&hw->phy->sync_txq);

>         netdev_dbg(dev, "transmission failed\n");
>  }
>
> @@ -117,6 +118,11 @@ ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
>         return ieee802154_tx(local, skb);
>  }
>
> +void ieee802154_sync_tx(struct ieee802154_local *local)
> +{
> +       wait_event(local->phy->sync_txq, !atomic_read(&local->phy->ongoing_txs));
> +}
> +
>  netdev_tx_t
>  ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  {
> diff --git a/net/mac802154/util.c b/net/mac802154/util.c
> index db2ac53b937e..230fe3390df7 100644
> --- a/net/mac802154/util.c
> +++ b/net/mac802154/util.c
> @@ -90,6 +90,7 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
>  after_wakeup:
>         dev_consume_skb_any(skb);
>         atomic_dec(&hw->phy->ongoing_txs);
> +       wake_up(&hw->phy->sync_txq);

if (atomic_dec_and_test(&hw->phy->ongoing_txs))
      wake_up(&hw->phy->sync_txq);

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods
  2022-01-17 11:54 ` [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods Miquel Raynal
@ 2022-01-17 22:52   ` Alexander Aring
  2022-01-18 18:20     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-17 22:52 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 06:54, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> These periods are expressed in time units (microseconds) while 40 and 12
> are the number of symbol durations these periods will last. We need to
> multiply them both with phy->symbol_duration in order to get these
> values in microseconds.
>
> Fixes: 8c6ad9cc5157 ("ieee802154: Add NXP MCR20A IEEE 802.15.4 transceiver driver")
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/net/ieee802154/mcr20a.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
> index f0eb2d3b1c4e..e2c249aef430 100644
> --- a/drivers/net/ieee802154/mcr20a.c
> +++ b/drivers/net/ieee802154/mcr20a.c
> @@ -976,8 +976,8 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
>         dev_dbg(printdev(lp), "%s\n", __func__);
>
>         phy->symbol_duration = 16;
> -       phy->lifs_period = 40;
> -       phy->sifs_period = 12;
> +       phy->lifs_period = 40 * phy->symbol_duration;
> +       phy->sifs_period = 12 * phy->symbol_duration;

I thought we do that now in register_hw(). Why does this patch exist?

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-17 11:54 ` [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over Miquel Raynal
@ 2022-01-17 22:58   ` Alexander Aring
  2022-01-18  0:34   ` Alexander Aring
  1 sibling, 0 replies; 62+ messages in thread
From: Alexander Aring @ 2022-01-17 22:58 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> ieee802154_xmit_complete() is the right helper to call when a
> transmission is over. The fact that it completed or not is not really a
> question, but drivers must tell the core that the completion is over,
> even if it was canceled. Do not call ieee802154_wake_queue() manually,
> in order to let full control of this task to the core.
>

This is not a cancellation of a transmission, it is something weird
going on.  Introduce a xmit_error() for this, you call consume_skb()
which is wrong for a non error case.

> By using the complete helper we also avoid leacking the skb structure.
>

Yes, we are leaking here.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 00/41] IEEE 802.15.4 scan support
  2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
                   ` (40 preceding siblings ...)
  2022-01-17 11:54 ` [PATCH v3 41/41] net: ieee802154: ca8210: Flag the driver as being limited Miquel Raynal
@ 2022-01-17 23:02 ` Alexander Aring
  2022-01-18 10:40   ` Miquel Raynal
  41 siblings, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-17 23:02 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 06:54, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hello,
>
>         *** TLDR ***
>
> Here is a series attempting to bring support for scans in the
> IEEE 802.15.4 stack. A number of improvements had to be made, including:
> * a better handling of the symbol durations
> * a few changes in Kconfig
> * a better handling of the tx queues
> * a synchronous Tx API
>
> Active and passive scans can be locally tested only with hwsim.
>
> Sorry for the big series, might be split in the near future.
>
>         ************
>
> A second series aligning the tooling with these changes is related,
> bringing support for a number of new features such as:
>
> * Sending (or stopping) beacons. Intervals ranging from 0 to 14 are
>   valid for passively sending beacons at regular intervals. An interval
>   of 15 would request the core to answer to received BEACON_REQ.
>   # iwpan dev wpan0 beacons send interval 2 # send BEACON at a fixed rate
>   # iwpan dev wpan0 beacons send interval 15 # answer BEACON_REQ only
>   # iwpan dev wpan0 beacons stop # apply to both cases
>
> * Scanning all the channels or only a subset:
>   # iwpan dev wpan1 scan type passive duration 3 # will not trigger BEACON_REQ
>   # iwpan dev wpan1 scan type active duration 3 # will trigger BEACON_REQ
>
> * If a beacon is received during a scan, the internal PAN list is
>   updated and can be dumped, flushed and configured with:
>   # iwpan dev wpan1 pans dump
>   PAN 0xffff (on wpan1)
>       coordinator 0x2efefdd4cdbf9330
>       page 0
>       channel 13
>       superframe spec. 0xcf22
>       LQI 0
>       seen 7156ms ago
>   # iwpan dev wpan1 pans flush
>   # iwpan dev wpan1 set max_pan_entries 100
>   # iwpan dev wpan1 set pans_expiration 3600
>
> * It is also possible to monitor the events with:
>   # iwpan event
>
> * As well as triggering a non blocking scan:
>   # iwpan dev wpan1 scan trigger type passive duration 3
>   # iwpan dev wpan1 scan done
>   # iwpan dev wpan1 scan abort
>
> The PAN list gets automatically updated by dropping the expired PANs
> each time the user requests access to the list.
>
> Internally, both requests (scan/beacons) are handled periodically by
> delayed workqueues when relevant.
>
> So far the only technical point that is missing in this series is the
> possibility to grab a reference over the module driving the net device
> in order to prevent module unloading during a scan or when the beacons
> work is ongoing.
>
> Finally, this series is a deep reshuffle of David Girault's original
> work, hence the fact that he is almost systematically credited, either
> by being the only author when I created the patches based on his changes
> with almost no modification, or with a Co-developped-by tag whenever the
> final code base is significantly different than his first proposal while
> still being greatly inspired from it.
>

can you please split this patch series, what I see is now:

1. cleanup patches
2. sync tx handling for mlme commands
3. scan support

we try to bring the patches upstream in this order.

Thanks.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 26/41] net: mac802154: Add a warning in the hot path
  2022-01-17 11:54 ` [PATCH v3 26/41] net: mac802154: Add a warning in the hot path Miquel Raynal
@ 2022-01-17 23:14   ` Alexander Aring
  2022-01-18 18:20     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-17 23:14 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> 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.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  net/mac802154/tx.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
> index 18ee6fcfcd7f..de5ecda80472 100644
> --- a/net/mac802154/tx.c
> +++ b/net/mac802154/tx.c
> @@ -112,6 +112,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
>  static netdev_tx_t
>  ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
>  {
> +       WARN_ON(mac802154_queue_is_stopped(local));
> +

we should do a WARN_ON_ONCE() in this hot function.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-17 11:54 ` [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over Miquel Raynal
  2022-01-17 22:58   ` Alexander Aring
@ 2022-01-18  0:34   ` Alexander Aring
  2022-01-18  0:36     ` Alexander Aring
  1 sibling, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-18  0:34 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> ieee802154_xmit_complete() is the right helper to call when a
> transmission is over. The fact that it completed or not is not really a
> question, but drivers must tell the core that the completion is over,
> even if it was canceled. Do not call ieee802154_wake_queue() manually,
> in order to let full control of this task to the core.
>
> By using the complete helper we also avoid leacking the skb structure.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/net/ieee802154/at86rf230.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> index 583f835c317a..1941e1f3d2ef 100644
> --- a/drivers/net/ieee802154/at86rf230.c
> +++ b/drivers/net/ieee802154/at86rf230.c
> @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
>         if (ctx->free)
>                 kfree(ctx);
>
> -       ieee802154_wake_queue(lp->hw);
> +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);

also this lp->tx_skb can be a dangled pointer, after xmit_complete()
we need to set it to NULL in a xmit_error() we can check on NULL
before calling kfree_skb().

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-18  0:34   ` Alexander Aring
@ 2022-01-18  0:36     ` Alexander Aring
  2022-01-18 18:22       ` Miquel Raynal
                         ` (2 more replies)
  0 siblings, 3 replies; 62+ messages in thread
From: Alexander Aring @ 2022-01-18  0:36 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Mon, 17 Jan 2022 at 19:34, Alexander Aring <alex.aring@gmail.com> wrote:
>
> Hi,
>
> On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > ieee802154_xmit_complete() is the right helper to call when a
> > transmission is over. The fact that it completed or not is not really a
> > question, but drivers must tell the core that the completion is over,
> > even if it was canceled. Do not call ieee802154_wake_queue() manually,
> > in order to let full control of this task to the core.
> >
> > By using the complete helper we also avoid leacking the skb structure.
> >
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/net/ieee802154/at86rf230.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> > index 583f835c317a..1941e1f3d2ef 100644
> > --- a/drivers/net/ieee802154/at86rf230.c
> > +++ b/drivers/net/ieee802154/at86rf230.c
> > @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
> >         if (ctx->free)
> >                 kfree(ctx);
> >
> > -       ieee802154_wake_queue(lp->hw);
> > +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
>
> also this lp->tx_skb can be a dangled pointer, after xmit_complete()
> we need to set it to NULL in a xmit_error() we can check on NULL
> before calling kfree_skb().
>

forget the NULL checking, it's already done by core. However in some
cases this is called with a dangled pointer on lp->tx_skb.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 00/41] IEEE 802.15.4 scan support
  2022-01-17 23:02 ` [PATCH v3 00/41] IEEE 802.15.4 scan support Alexander Aring
@ 2022-01-18 10:40   ` Miquel Raynal
  2022-01-18 23:12     ` Alexander Aring
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-18 10:40 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

> > So far the only technical point that is missing in this series is the
> > possibility to grab a reference over the module driving the net device
> > in order to prevent module unloading during a scan or when the beacons
> > work is ongoing.

Do you have any advises regarding this issue? That is the only
technical point that is left unaddressed IMHO.

> > Finally, this series is a deep reshuffle of David Girault's original
> > work, hence the fact that he is almost systematically credited, either
> > by being the only author when I created the patches based on his changes
> > with almost no modification, or with a Co-developped-by tag whenever the
> > final code base is significantly different than his first proposal while
> > still being greatly inspired from it.
> >  
> 
> can you please split this patch series, what I see is now:
> 
> 1. cleanup patches
> 2. sync tx handling for mlme commands
> 3. scan support

Works for me. I just wanted to give the big picture but I'll split the
series.

Also sorry for forgetting the 'wpan-next' subject prefix.

> we try to bring the patches upstream in this order.
> 
> Thanks.
> 
> - Alex


Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism
  2022-01-17 22:43   ` Alexander Aring
@ 2022-01-18 18:14     ` Miquel Raynal
  2022-01-18 23:16       ` Alexander Aring
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-18 18:14 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Mon, 17 Jan 2022 17:43:49 -0500:

> Hi,
> 
> On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> ...
> >
> >         /* stop hardware - this must stop RX */
> > diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
> > index 0291e49058f2..37d5438fdb3f 100644
> > --- a/net/mac802154/ieee802154_i.h
> > +++ b/net/mac802154/ieee802154_i.h
> > @@ -122,6 +122,7 @@ extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
> >
> >  void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
> >  void ieee802154_xmit_sync_worker(struct work_struct *work);
> > +void ieee802154_sync_tx(struct ieee802154_local *local);
> >  netdev_tx_t
> >  ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
> >  netdev_tx_t
> > diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
> > index de5ecda80472..d1fd2cc67cbe 100644
> > --- a/net/mac802154/tx.c
> > +++ b/net/mac802154/tx.c
> > @@ -48,6 +48,7 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
> >
> >         kfree_skb(skb);
> >         atomic_dec(&local->phy->ongoing_txs);
> > +       wake_up(&local->phy->sync_txq);  
> 
> if (atomic_dec_and_test(&hw->phy->ongoing_txs))
>       wake_up(&hw->phy->sync_txq);

As we test this condition in the waiting path I assumed it was fine to
do it this way, but the additional check does not hurt, so I'll add it.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods
  2022-01-17 22:52   ` Alexander Aring
@ 2022-01-18 18:20     ` Miquel Raynal
  2022-01-18 22:53       ` Alexander Aring
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-18 18:20 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Mon, 17 Jan 2022 17:52:10 -0500:

> Hi,
> 
> On Mon, 17 Jan 2022 at 06:54, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > These periods are expressed in time units (microseconds) while 40 and 12
> > are the number of symbol durations these periods will last. We need to
> > multiply them both with phy->symbol_duration in order to get these
> > values in microseconds.
> >
> > Fixes: 8c6ad9cc5157 ("ieee802154: Add NXP MCR20A IEEE 802.15.4 transceiver driver")
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/net/ieee802154/mcr20a.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
> > index f0eb2d3b1c4e..e2c249aef430 100644
> > --- a/drivers/net/ieee802154/mcr20a.c
> > +++ b/drivers/net/ieee802154/mcr20a.c
> > @@ -976,8 +976,8 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
> >         dev_dbg(printdev(lp), "%s\n", __func__);
> >
> >         phy->symbol_duration = 16;
> > -       phy->lifs_period = 40;
> > -       phy->sifs_period = 12;
> > +       phy->lifs_period = 40 * phy->symbol_duration;
> > +       phy->sifs_period = 12 * phy->symbol_duration;  
> 
> I thought we do that now in register_hw(). Why does this patch exist?

The lifs and sifs period are wrong.

Fixing this silently by generalizing the calculation is simply wrong. I
feel we need to do this in order:
1- Fix the period because it is wrong.
2- Now that the period is set to a valid value and the core is able to
   do the same operation and set the variables to an identical content,
   we can drop these lines from the driver. 

#2 being a mechanical change, doing it without #1 means that something
that appears harmless actually changes the behavior of the driver. We
generally try to avoid that, no?

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 26/41] net: mac802154: Add a warning in the hot path
  2022-01-17 23:14   ` Alexander Aring
@ 2022-01-18 18:20     ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-18 18:20 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Mon, 17 Jan 2022 18:14:17 -0500:

> Hi,
> 
> On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > 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.
> >
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  net/mac802154/tx.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
> > index 18ee6fcfcd7f..de5ecda80472 100644
> > --- a/net/mac802154/tx.c
> > +++ b/net/mac802154/tx.c
> > @@ -112,6 +112,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
> >  static netdev_tx_t
> >  ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
> >  {
> > +       WARN_ON(mac802154_queue_is_stopped(local));
> > +  
> 
> we should do a WARN_ON_ONCE() in this hot function.

Sure!

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-18  0:36     ` Alexander Aring
@ 2022-01-18 18:22       ` Miquel Raynal
  2022-01-19 22:45       ` Miquel Raynal
  2022-01-19 22:56       ` Miquel Raynal
  2 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-18 18:22 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Mon, 17 Jan 2022 19:36:39 -0500:

> Hi,
> 
> On Mon, 17 Jan 2022 at 19:34, Alexander Aring <alex.aring@gmail.com> wrote:
> >
> > Hi,
> >
> > On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:  
> > >
> > > ieee802154_xmit_complete() is the right helper to call when a
> > > transmission is over. The fact that it completed or not is not really a
> > > question, but drivers must tell the core that the completion is over,
> > > even if it was canceled. Do not call ieee802154_wake_queue() manually,
> > > in order to let full control of this task to the core.
> > >
> > > By using the complete helper we also avoid leacking the skb structure.
> > >
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/net/ieee802154/at86rf230.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> > > index 583f835c317a..1941e1f3d2ef 100644
> > > --- a/drivers/net/ieee802154/at86rf230.c
> > > +++ b/drivers/net/ieee802154/at86rf230.c
> > > @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
> > >         if (ctx->free)
> > >                 kfree(ctx);
> > >
> > > -       ieee802154_wake_queue(lp->hw);
> > > +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);  
> >
> > also this lp->tx_skb can be a dangled pointer, after xmit_complete()
> > we need to set it to NULL in a xmit_error() we can check on NULL
> > before calling kfree_skb().
> >  
> 
> forget the NULL checking, it's already done by core. However in some
> cases this is called with a dangled pointer on lp->tx_skb.

I'll try to fix these dangling situation first if I find them.

I'll also introduce a xmit_error() helper as you suggest.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods
  2022-01-18 18:20     ` Miquel Raynal
@ 2022-01-18 22:53       ` Alexander Aring
  0 siblings, 0 replies; 62+ messages in thread
From: Alexander Aring @ 2022-01-18 22:53 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Tue, 18 Jan 2022 at 13:20, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> alex.aring@gmail.com wrote on Mon, 17 Jan 2022 17:52:10 -0500:
>
> > Hi,
> >
> > On Mon, 17 Jan 2022 at 06:54, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > >
> > > These periods are expressed in time units (microseconds) while 40 and 12
> > > are the number of symbol durations these periods will last. We need to
> > > multiply them both with phy->symbol_duration in order to get these
> > > values in microseconds.
> > >
> > > Fixes: 8c6ad9cc5157 ("ieee802154: Add NXP MCR20A IEEE 802.15.4 transceiver driver")
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/net/ieee802154/mcr20a.c | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
> > > index f0eb2d3b1c4e..e2c249aef430 100644
> > > --- a/drivers/net/ieee802154/mcr20a.c
> > > +++ b/drivers/net/ieee802154/mcr20a.c
> > > @@ -976,8 +976,8 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp)
> > >         dev_dbg(printdev(lp), "%s\n", __func__);
> > >
> > >         phy->symbol_duration = 16;
> > > -       phy->lifs_period = 40;
> > > -       phy->sifs_period = 12;
> > > +       phy->lifs_period = 40 * phy->symbol_duration;
> > > +       phy->sifs_period = 12 * phy->symbol_duration;
> >
> > I thought we do that now in register_hw(). Why does this patch exist?
>
> The lifs and sifs period are wrong.
>
> Fixing this silently by generalizing the calculation is simply wrong. I
> feel we need to do this in order:
> 1- Fix the period because it is wrong.
> 2- Now that the period is set to a valid value and the core is able to
>    do the same operation and set the variables to an identical content,
>    we can drop these lines from the driver.
>
> #2 being a mechanical change, doing it without #1 means that something
> that appears harmless actually changes the behavior of the driver. We
> generally try to avoid that, no?

yes, maybe Stefan can get this patch then somehow to wpan and queue it
for stable.

Thanks for clarification.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 00/41] IEEE 802.15.4 scan support
  2022-01-18 10:40   ` Miquel Raynal
@ 2022-01-18 23:12     ` Alexander Aring
  2022-01-20  0:24       ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-18 23:12 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Tue, 18 Jan 2022 at 05:40, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> > > So far the only technical point that is missing in this series is the
> > > possibility to grab a reference over the module driving the net device
> > > in order to prevent module unloading during a scan or when the beacons
> > > work is ongoing.
>
> Do you have any advises regarding this issue? That is the only
> technical point that is left unaddressed IMHO.
>

module_get()/module_put() or I don't see where the problem here is.
You can avoid module unloading with it. Which module is the problem
here?

> > > Finally, this series is a deep reshuffle of David Girault's original
> > > work, hence the fact that he is almost systematically credited, either
> > > by being the only author when I created the patches based on his changes
> > > with almost no modification, or with a Co-developped-by tag whenever the
> > > final code base is significantly different than his first proposal while
> > > still being greatly inspired from it.
> > >
> >
> > can you please split this patch series, what I see is now:
> >
> > 1. cleanup patches
> > 2. sync tx handling for mlme commands
> > 3. scan support
>
> Works for me. I just wanted to give the big picture but I'll split the
> series.
>

maybe also put some "symbol duration" series into it if it's getting
too large? It is difficult to review 40 patches... in one step.

> Also sorry for forgetting the 'wpan-next' subject prefix.
>

no problem.

I really appreciate your work and your willingness to work on all
outstanding issues. I am really happy to see something that we can use
for mlme-commands and to separate it from the hotpath transmission...
It is good to see architecture for that which I think goes in the
right direction.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism
  2022-01-18 18:14     ` Miquel Raynal
@ 2022-01-18 23:16       ` Alexander Aring
  0 siblings, 0 replies; 62+ messages in thread
From: Alexander Aring @ 2022-01-18 23:16 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Tue, 18 Jan 2022 at 13:14, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> alex.aring@gmail.com wrote on Mon, 17 Jan 2022 17:43:49 -0500:
>
> > Hi,
> >
> > On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > ...
> > >
> > >         /* stop hardware - this must stop RX */
> > > diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
> > > index 0291e49058f2..37d5438fdb3f 100644
> > > --- a/net/mac802154/ieee802154_i.h
> > > +++ b/net/mac802154/ieee802154_i.h
> > > @@ -122,6 +122,7 @@ extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
> > >
> > >  void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
> > >  void ieee802154_xmit_sync_worker(struct work_struct *work);
> > > +void ieee802154_sync_tx(struct ieee802154_local *local);
> > >  netdev_tx_t
> > >  ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
> > >  netdev_tx_t
> > > diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
> > > index de5ecda80472..d1fd2cc67cbe 100644
> > > --- a/net/mac802154/tx.c
> > > +++ b/net/mac802154/tx.c
> > > @@ -48,6 +48,7 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
> > >
> > >         kfree_skb(skb);
> > >         atomic_dec(&local->phy->ongoing_txs);
> > > +       wake_up(&local->phy->sync_txq);
> >
> > if (atomic_dec_and_test(&hw->phy->ongoing_txs))
> >       wake_up(&hw->phy->sync_txq);
>
> As we test this condition in the waiting path I assumed it was fine to
> do it this way, but the additional check does not hurt, so I'll add it.

it's just a nitpick... to avoid scheduling and this triggers a
checking if the condition is true in cases we know it can't....

although we can talk about this because ongoing_txs should never be
higher than 1... so any atomic_dec() should make the condition true...

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-18  0:36     ` Alexander Aring
  2022-01-18 18:22       ` Miquel Raynal
@ 2022-01-19 22:45       ` Miquel Raynal
  2022-01-19 22:56       ` Miquel Raynal
  2 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-19 22:45 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Mon, 17 Jan 2022 19:36:39 -0500:

> Hi,
> 
> On Mon, 17 Jan 2022 at 19:34, Alexander Aring <alex.aring@gmail.com> wrote:
> >
> > Hi,
> >
> > On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:  
> > >
> > > ieee802154_xmit_complete() is the right helper to call when a
> > > transmission is over. The fact that it completed or not is not really a
> > > question, but drivers must tell the core that the completion is over,
> > > even if it was canceled. Do not call ieee802154_wake_queue() manually,
> > > in order to let full control of this task to the core.
> > >
> > > By using the complete helper we also avoid leacking the skb structure.
> > >
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/net/ieee802154/at86rf230.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> > > index 583f835c317a..1941e1f3d2ef 100644
> > > --- a/drivers/net/ieee802154/at86rf230.c
> > > +++ b/drivers/net/ieee802154/at86rf230.c
> > > @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
> > >         if (ctx->free)
> > >                 kfree(ctx);
> > >
> > > -       ieee802154_wake_queue(lp->hw);
> > > +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);  
> >
> > also this lp->tx_skb can be a dangled pointer, after xmit_complete()
> > we need to set it to NULL in a xmit_error() we can check on NULL
> > before calling kfree_skb().

I've created a xmit_error() helper as suggested, which call
dev_kfree_skb_any() instead of *consume_skb*().

> 
> forget the NULL checking, it's already done by core.

Indeed, it is.

> However in some
> cases this is called with a dangled pointer on lp->tx_skb.

I've fixed that by setting it to NULL after the call to the xmit_error
helper.

> 
> - Alex


Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-18  0:36     ` Alexander Aring
  2022-01-18 18:22       ` Miquel Raynal
  2022-01-19 22:45       ` Miquel Raynal
@ 2022-01-19 22:56       ` Miquel Raynal
  2022-01-19 23:34         ` Alexander Aring
  2 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2022-01-19 22:56 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Mon, 17 Jan 2022 19:36:39 -0500:

> Hi,
> 
> On Mon, 17 Jan 2022 at 19:34, Alexander Aring <alex.aring@gmail.com> wrote:
> >
> > Hi,
> >
> > On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:  
> > >
> > > ieee802154_xmit_complete() is the right helper to call when a
> > > transmission is over. The fact that it completed or not is not really a
> > > question, but drivers must tell the core that the completion is over,
> > > even if it was canceled. Do not call ieee802154_wake_queue() manually,
> > > in order to let full control of this task to the core.
> > >
> > > By using the complete helper we also avoid leacking the skb structure.
> > >
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/net/ieee802154/at86rf230.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> > > index 583f835c317a..1941e1f3d2ef 100644
> > > --- a/drivers/net/ieee802154/at86rf230.c
> > > +++ b/drivers/net/ieee802154/at86rf230.c
> > > @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
> > >         if (ctx->free)
> > >                 kfree(ctx);
> > >
> > > -       ieee802154_wake_queue(lp->hw);
> > > +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);  
> >
> > also this lp->tx_skb can be a dangled pointer, after xmit_complete()
> > we need to set it to NULL in a xmit_error() we can check on NULL
> > before calling kfree_skb().
> >  
> 
> forget the NULL checking, it's already done by core. However in some
> cases this is called with a dangled pointer on lp->tx_skb.

Actually I don't see why tx_skb is dangling?

There is no function that could accesses lp->tx_skb between the free
operation and the next call to ->xmit() which does a lp->tx_skb = skb.
Am I missing something?

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-19 22:56       ` Miquel Raynal
@ 2022-01-19 23:34         ` Alexander Aring
  2022-01-20  0:19           ` Alexander Aring
  0 siblings, 1 reply; 62+ messages in thread
From: Alexander Aring @ 2022-01-19 23:34 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Wed, 19 Jan 2022 at 17:56, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> alex.aring@gmail.com wrote on Mon, 17 Jan 2022 19:36:39 -0500:
>
> > Hi,
> >
> > On Mon, 17 Jan 2022 at 19:34, Alexander Aring <alex.aring@gmail.com> wrote:
> > >
> > > Hi,
> > >
> > > On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > > >
> > > > ieee802154_xmit_complete() is the right helper to call when a
> > > > transmission is over. The fact that it completed or not is not really a
> > > > question, but drivers must tell the core that the completion is over,
> > > > even if it was canceled. Do not call ieee802154_wake_queue() manually,
> > > > in order to let full control of this task to the core.
> > > >
> > > > By using the complete helper we also avoid leacking the skb structure.
> > > >
> > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > ---
> > > >  drivers/net/ieee802154/at86rf230.c | 2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> > > > index 583f835c317a..1941e1f3d2ef 100644
> > > > --- a/drivers/net/ieee802154/at86rf230.c
> > > > +++ b/drivers/net/ieee802154/at86rf230.c
> > > > @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
> > > >         if (ctx->free)
> > > >                 kfree(ctx);
> > > >
> > > > -       ieee802154_wake_queue(lp->hw);
> > > > +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
> > >
> > > also this lp->tx_skb can be a dangled pointer, after xmit_complete()
> > > we need to set it to NULL in a xmit_error() we can check on NULL
> > > before calling kfree_skb().
> > >
> >
> > forget the NULL checking, it's already done by core. However in some
> > cases this is called with a dangled pointer on lp->tx_skb.
>
> Actually I don't see why tx_skb is dangling?
>
> There is no function that could accesses lp->tx_skb between the free
> operation and the next call to ->xmit() which does a lp->tx_skb = skb.
> Am I missing something?
>

look into at86rf230_sync_state_change() it is a sync over async and
the function "at86rf230_async_error_recover_complete()" is a generic
error handling to recover from a state change. It's e.g. being used in
e.g. at86rf230_start() which can occur in cases which are not xmit
related.

Indeed there is no dangled pointer in the irq handling, sorry. I
thought maybe the receive handling but the transceiver is doing a lot
of its own state change handling because of some framebuffer
protection which is not the case.

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over
  2022-01-19 23:34         ` Alexander Aring
@ 2022-01-20  0:19           ` Alexander Aring
  0 siblings, 0 replies; 62+ messages in thread
From: Alexander Aring @ 2022-01-20  0:19 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi,

On Wed, 19 Jan 2022 at 18:34, Alexander Aring <alex.aring@gmail.com> wrote:
>
> Hi,
>
> On Wed, 19 Jan 2022 at 17:56, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > Hi Alexander,
> >
> > alex.aring@gmail.com wrote on Mon, 17 Jan 2022 19:36:39 -0500:
> >
> > > Hi,
> > >
> > > On Mon, 17 Jan 2022 at 19:34, Alexander Aring <alex.aring@gmail.com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > On Mon, 17 Jan 2022 at 06:55, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > > > >
> > > > > ieee802154_xmit_complete() is the right helper to call when a
> > > > > transmission is over. The fact that it completed or not is not really a
> > > > > question, but drivers must tell the core that the completion is over,
> > > > > even if it was canceled. Do not call ieee802154_wake_queue() manually,
> > > > > in order to let full control of this task to the core.
> > > > >
> > > > > By using the complete helper we also avoid leacking the skb structure.
> > > > >
> > > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > > ---
> > > > >  drivers/net/ieee802154/at86rf230.c | 2 +-
> > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
> > > > > index 583f835c317a..1941e1f3d2ef 100644
> > > > > --- a/drivers/net/ieee802154/at86rf230.c
> > > > > +++ b/drivers/net/ieee802154/at86rf230.c
> > > > > @@ -343,7 +343,7 @@ at86rf230_async_error_recover_complete(void *context)
> > > > >         if (ctx->free)
> > > > >                 kfree(ctx);
> > > > >
> > > > > -       ieee802154_wake_queue(lp->hw);
> > > > > +       ieee802154_xmit_complete(lp->hw, lp->tx_skb, false);
> > > >
> > > > also this lp->tx_skb can be a dangled pointer, after xmit_complete()
> > > > we need to set it to NULL in a xmit_error() we can check on NULL
> > > > before calling kfree_skb().
> > > >
> > >
> > > forget the NULL checking, it's already done by core. However in some
> > > cases this is called with a dangled pointer on lp->tx_skb.
> >
> > Actually I don't see why tx_skb is dangling?
> >
> > There is no function that could accesses lp->tx_skb between the free
> > operation and the next call to ->xmit() which does a lp->tx_skb = skb.
> > Am I missing something?
> >
>
> look into at86rf230_sync_state_change() it is a sync over async and
> the function "at86rf230_async_error_recover_complete()" is a generic
> error handling to recover from a state change. It's e.g. being used in
> e.g. at86rf230_start() which can occur in cases which are not xmit
> related.
>

which means there is more being broken that we should not simply call
to wake the queue in non-transmit cases...

- Alex

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v3 00/41] IEEE 802.15.4 scan support
  2022-01-18 23:12     ` Alexander Aring
@ 2022-01-20  0:24       ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2022-01-20  0:24 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Stefan Schmidt, linux-wpan - ML, open list:NETWORKING [GENERAL],
	linux-wireless@vger.kernel.org Wireless, David Girault,
	Romuald Despres, Frederic Blain, Nicolas Schodet,
	Michael Hennerich, Jakub Kicinski, Varka Bhadram, Xue Liu,
	Alan Ott, Thomas Petazzoni

Hi Alexander,

alex.aring@gmail.com wrote on Tue, 18 Jan 2022 18:12:49 -0500:

> Hi,
> 
> On Tue, 18 Jan 2022 at 05:40, Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > Hi Alexander,
> >  
> > > > So far the only technical point that is missing in this series is the
> > > > possibility to grab a reference over the module driving the net device
> > > > in order to prevent module unloading during a scan or when the beacons
> > > > work is ongoing.  
> >
> > Do you have any advises regarding this issue? That is the only
> > technical point that is left unaddressed IMHO.
> >  
> 
> module_get()/module_put() or I don't see where the problem here is.
> You can avoid module unloading with it. Which module is the problem
> here?

I'll give it another try, maybe when I first tried that I was missing a
few mental peaces and did not understood the puzzle correctly.

> > > > Finally, this series is a deep reshuffle of David Girault's original
> > > > work, hence the fact that he is almost systematically credited, either
> > > > by being the only author when I created the patches based on his changes
> > > > with almost no modification, or with a Co-developped-by tag whenever the
> > > > final code base is significantly different than his first proposal while
> > > > still being greatly inspired from it.
> > > >  
> > >
> > > can you please split this patch series, what I see is now:
> > >
> > > 1. cleanup patches
> > > 2. sync tx handling for mlme commands
> > > 3. scan support  
> >
> > Works for me. I just wanted to give the big picture but I'll split the
> > series.
> >  
> 
> maybe also put some "symbol duration" series into it if it's getting
> too large? It is difficult to review 40 patches... in one step.

Yep, I truly understand (and now 50+).

> 
> > Also sorry for forgetting the 'wpan-next' subject prefix.
> >  
> 
> no problem.
> 
> I really appreciate your work and your willingness to work on all
> outstanding issues. I am really happy to see something that we can use
> for mlme-commands and to separate it from the hotpath transmission...
> It is good to see architecture for that which I think goes in the
> right direction.

That is very stirring to read :)

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2022-01-20  0:25 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 01/41] MAINTAINERS: Remove Harry Morris bouncing address Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 02/41] net: ieee802154: hwsim: Ensure proper channel selection at probe time Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 03/41] net: ieee802154: hwsim: Ensure frame checksum are valid Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 04/41] net: ieee802154: Use the IEEE802154_MAX_PAGE define when relevant Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 05/41] net: ieee802154: Improve the way supported channels are declared Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 06/41] net: ieee802154: Give more details to the core about the channel configurations Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods Miquel Raynal
2022-01-17 22:52   ` Alexander Aring
2022-01-18 18:20     ` Miquel Raynal
2022-01-18 22:53       ` Alexander Aring
2022-01-17 11:54 ` [PATCH v3 08/41] net: mac802154: Convert the symbol duration into nanoseconds Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 09/41] net: mac802154: Set the symbol duration automatically Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 10/41] net: ieee802154: Drop duration settings when the core does it already Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 11/41] net: ieee802154: Move IEEE 802.15.4 Kconfig main entry Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 12/41] net: mac802154: Include the softMAC stack inside the IEEE 802.15.4 menu Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 13/41] net: ieee802154: Move the address structure earlier Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 14/41] net: ieee802154: Add a kernel doc header to the ieee802154_addr structure Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 15/41] net: ieee802154: Return meaningful error codes from the netlink helpers Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 16/41] net: mac802154: Explain the use of ieee802154_wake/stop_queue() Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over Miquel Raynal
2022-01-17 22:58   ` Alexander Aring
2022-01-18  0:34   ` Alexander Aring
2022-01-18  0:36     ` Alexander Aring
2022-01-18 18:22       ` Miquel Raynal
2022-01-19 22:45       ` Miquel Raynal
2022-01-19 22:56       ` Miquel Raynal
2022-01-19 23:34         ` Alexander Aring
2022-01-20  0:19           ` Alexander Aring
2022-01-17 11:54 ` [PATCH v3 18/41] net: ieee802154: atusb: " Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 19/41] net: ieee802154: ca8210: " Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 20/41] net: mac802154: Stop exporting ieee802154_wake/stop_queue() Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 21/41] net: mac802154: Rename the synchronous xmit worker Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 22/41] net: mac802154: Rename the main tx_work struct Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 23/41] net: mac802154: Follow the count of ongoing transmissions Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 24/41] net: mac802154: Hold the transmit queue when relevant Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 25/41] net: mac802154: Create a hot tx path Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 26/41] net: mac802154: Add a warning in the hot path Miquel Raynal
2022-01-17 23:14   ` Alexander Aring
2022-01-18 18:20     ` Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism Miquel Raynal
2022-01-17 22:43   ` Alexander Aring
2022-01-18 18:14     ` Miquel Raynal
2022-01-18 23:16       ` Alexander Aring
2022-01-17 11:54 ` [PATCH v3 28/41] net: mac802154: Introduce a synchronous API for MLME commands Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 29/41] net: ieee802154: Add support for internal PAN management Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 30/41] net: ieee802154: Define a beacon frame header Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 31/41] net: ieee802154: Define frame types Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 32/41] net: ieee802154: Add support for scanning requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 33/41] net: mac802154: Handle scan requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 34/41] net: ieee802154: Full PAN management Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 35/41] net: ieee802154: Add beacons support Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 36/41] net: mac802154: Handle beacons requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 37/41] net: ieee802154: Trace the registration of new PANs Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 38/41] net: mac802154: Add support for active scans Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 39/41] net: mac802154: Add support for processing beacon requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 40/41] net: ieee802154: Handle limited devices with only datagram support Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 41/41] net: ieee802154: ca8210: Flag the driver as being limited Miquel Raynal
2022-01-17 23:02 ` [PATCH v3 00/41] IEEE 802.15.4 scan support Alexander Aring
2022-01-18 10:40   ` Miquel Raynal
2022-01-18 23:12     ` Alexander Aring
2022-01-20  0:24       ` Miquel Raynal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).