net: mac802154: Set durations automatically
authorMiquel Raynal <miquel.raynal@bootlin.com>
Tue, 1 Feb 2022 18:06:28 +0000 (19:06 +0100)
committerStefan Schmidt <stefan@datenfreihafen.org>
Thu, 10 Feb 2022 14:41:58 +0000 (15:41 +0100)
As depicted in the IEEE 802.15.4 specification, modulation/bands are
tight to a number of page/channels so we can for most of them derive the
durations automatically.

The two locations that must call this new helper to set the variou
symbol durations are:
- when manually requesting a channel change though the netlink interface
- at PHY creation, once the device driver has set the default
  page/channel

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.

Once the symbol duration derived, the lifs and sifs durations are
updated as well.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Acked-by: Alexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/r/20220201180629.93410-4-miquel.raynal@bootlin.com
Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
include/net/cfg802154.h
net/mac802154/cfg.c
net/mac802154/main.c

index 92d4f17..85f9e84 100644 (file)
@@ -415,4 +415,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 */
index fbeebe3..1e4a9f7 100644 (file)
@@ -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;
index 5315336..5546ef8 100644 (file)
@@ -113,6 +113,50 @@ 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)
+{
+       u32 duration = 0;
+
+       switch (phy->current_page) {
+       case 0:
+               if (BIT(phy->current_page) & 0x1)
+                       /* 868 MHz BPSK 802.15.4-2003: 20 ksym/s */
+                       duration = 50 * NSEC_PER_USEC;
+               else if (phy->current_page & 0x7FE)
+                       /* 915 MHz BPSK 802.15.4-2003: 40 ksym/s */
+                       duration = 25 * NSEC_PER_USEC;
+               else if (phy->current_page & 0x7FFF800)
+                       /* 2400 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
+                       duration = 16 * NSEC_PER_USEC;
+               break;
+       case 2:
+               if (BIT(phy->current_page) & 0x1)
+                       /* 868 MHz O-QPSK 802.15.4-2006: 25 ksym/s */
+                       duration = 40 * NSEC_PER_USEC;
+               else if (phy->current_page & 0x7FE)
+                       /* 915 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
+                       duration = 16 * NSEC_PER_USEC;
+               break;
+       case 3:
+               if (BIT(phy->current_page) & 0x3FFF)
+                       /* 2.4 GHz CSS 802.15.4a-2007: 1/6 Msym/s */
+                       duration = 6 * NSEC_PER_USEC;
+               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 +201,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;