wifi: iwlwifi: mvm: support 320 MHz PHY configuration
authorJohannes Berg <johannes.berg@intel.com>
Tue, 22 Nov 2022 20:10:33 +0000 (22:10 +0200)
committerGregory Greenman <gregory.greenman@intel.com>
Mon, 28 Nov 2022 15:53:01 +0000 (17:53 +0200)
Support 320 MHz PHY configuration and while doing so rewrite
the code since we'd otherwise double the number of cases in
the switch statement.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://lore.kernel.org/r/20221122220713.964db911b733.If56c94a9bf20c050f35d2421b680e400a9f4aeb8@changeid
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c

index e66f779..2f7d855 100644 (file)
 #define PHY_BAND_6 (2)
 
 /* Supported channel width, vary if there is VHT support */
-#define PHY_VHT_CHANNEL_MODE20 (0x0)
-#define PHY_VHT_CHANNEL_MODE40 (0x1)
-#define PHY_VHT_CHANNEL_MODE80 (0x2)
-#define PHY_VHT_CHANNEL_MODE160        (0x3)
+#define IWL_PHY_CHANNEL_MODE20 0x0
+#define IWL_PHY_CHANNEL_MODE40 0x1
+#define IWL_PHY_CHANNEL_MODE80 0x2
+#define IWL_PHY_CHANNEL_MODE160        0x3
+/* and 320 MHz for EHT */
+#define IWL_PHY_CHANNEL_MODE320        0x4
 
 /*
  * Control channel position:
  * For VHT - bit-2 marks if the control is lower/upper relative to center-freq
  *   bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.
  *                                   center_freq
- *                                        |
- * 40Mhz                          |_______|_______|
- * 80Mhz                  |_______|_______|_______|_______|
- * 160Mhz |_______|_______|_______|_______|_______|_______|_______|_______|
- * code      011     010     001     000  |  100     101     110    111
+ * For EHT - bit-3 is used for extended distance
+ *                                                |
+ * 40Mhz                                     |____|____|
+ * 80Mhz                                |____|____|____|____|
+ * 160Mhz                     |____|____|____|____|____|____|____|____|
+ * 320MHz |____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
+ * code    1011 1010 1001 1000 0011 0010 0001 0000 0100 0101 0110 0111 1100 1101 1110 1111
  */
-#define PHY_VHT_CTRL_POS_1_BELOW  (0x0)
-#define PHY_VHT_CTRL_POS_2_BELOW  (0x1)
-#define PHY_VHT_CTRL_POS_3_BELOW  (0x2)
-#define PHY_VHT_CTRL_POS_4_BELOW  (0x3)
-#define PHY_VHT_CTRL_POS_1_ABOVE  (0x4)
-#define PHY_VHT_CTRL_POS_2_ABOVE  (0x5)
-#define PHY_VHT_CTRL_POS_3_ABOVE  (0x6)
-#define PHY_VHT_CTRL_POS_4_ABOVE  (0x7)
+#define IWL_PHY_CTRL_POS_ABOVE         0x4
+#define IWL_PHY_CTRL_POS_OFFS_EXT      0x8
+#define IWL_PHY_CTRL_POS_OFFS_MSK      0x3
 
 /*
  * struct iwl_fw_channel_info_v1 - channel information
index a81dd48..57aa104 100644 (file)
@@ -3777,7 +3777,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
        /* Set the channel info data */
        iwl_mvm_set_chan_info(mvm, &aux_roc_req.channel_info, channel->hw_value,
                              iwl_mvm_phy_band_from_nl80211(channel->band),
-                             PHY_VHT_CHANNEL_MODE20,
+                             IWL_PHY_CHANNEL_MODE20,
                              0);
 
        /* Set the time and duration */
index a3cefbc..06f4203 100644 (file)
@@ -14,16 +14,18 @@ u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
        switch (chandef->width) {
        case NL80211_CHAN_WIDTH_20_NOHT:
        case NL80211_CHAN_WIDTH_20:
-               return PHY_VHT_CHANNEL_MODE20;
+               return IWL_PHY_CHANNEL_MODE20;
        case NL80211_CHAN_WIDTH_40:
-               return PHY_VHT_CHANNEL_MODE40;
+               return IWL_PHY_CHANNEL_MODE40;
        case NL80211_CHAN_WIDTH_80:
-               return PHY_VHT_CHANNEL_MODE80;
+               return IWL_PHY_CHANNEL_MODE80;
        case NL80211_CHAN_WIDTH_160:
-               return PHY_VHT_CHANNEL_MODE160;
+               return IWL_PHY_CHANNEL_MODE160;
+       case NL80211_CHAN_WIDTH_320:
+               return IWL_PHY_CHANNEL_MODE320;
        default:
                WARN(1, "Invalid channel width=%u", chandef->width);
-               return PHY_VHT_CHANNEL_MODE20;
+               return IWL_PHY_CHANNEL_MODE20;
        }
 }
 
@@ -33,34 +35,32 @@ u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
  */
 u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
 {
-       switch (chandef->chan->center_freq - chandef->center_freq1) {
-       case -70:
-               return PHY_VHT_CTRL_POS_4_BELOW;
-       case -50:
-               return PHY_VHT_CTRL_POS_3_BELOW;
-       case -30:
-               return PHY_VHT_CTRL_POS_2_BELOW;
-       case -10:
-               return PHY_VHT_CTRL_POS_1_BELOW;
-       case  10:
-               return PHY_VHT_CTRL_POS_1_ABOVE;
-       case  30:
-               return PHY_VHT_CTRL_POS_2_ABOVE;
-       case  50:
-               return PHY_VHT_CTRL_POS_3_ABOVE;
-       case  70:
-               return PHY_VHT_CTRL_POS_4_ABOVE;
-       default:
-               WARN(1, "Invalid channel definition");
-               fallthrough;
-       case 0:
+       int offs = chandef->chan->center_freq - chandef->center_freq1;
+       int abs_offs = abs(offs);
+       u8 ret;
+
+       if (offs == 0) {
                /*
                 * The FW is expected to check the control channel position only
                 * when in HT/VHT and the channel width is not 20MHz. Return
                 * this value as the default one.
                 */
-               return PHY_VHT_CTRL_POS_1_BELOW;
+               return 0;
        }
+
+       /* this results in a value 0-7, i.e. fitting into 0b0111 */
+       ret = (abs_offs - 10) / 20;
+       /*
+        * But we need the value to be in 0b1011 because 0b0100 is
+        * IWL_PHY_CTRL_POS_ABOVE, so shift bit 2 up to land in
+        * IWL_PHY_CTRL_POS_OFFS_EXT (0b1000)
+        */
+       ret = (ret & IWL_PHY_CTRL_POS_OFFS_MSK) |
+             ((ret & BIT(2)) << 1);
+       /* and add the above bit */
+       ret |= (offs > 0) * IWL_PHY_CTRL_POS_ABOVE;
+
+       return ret;
 }
 
 /*