add support for the iwx RLC config command
authorstsp <stsp@openbsd.org>
Mon, 6 Mar 2023 10:52:16 +0000 (10:52 +0000)
committerstsp <stsp@openbsd.org>
Mon, 6 Mar 2023 10:52:16 +0000 (10:52 +0000)
New firmware wants to be told about MIMO antenna configuration via
a separate command, rather than via the good old PHY context command.

sys/dev/pci/if_iwx.c
sys/dev/pci/if_iwxreg.h

index 90e45ec..5b98d32 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwx.c,v 1.158 2023/03/06 10:48:05 stsp Exp $       */
+/*     $OpenBSD: if_iwx.c,v 1.159 2023/03/06 10:52:16 stsp Exp $       */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -454,6 +454,8 @@ int iwx_rs_init_v3(struct iwx_softc *, struct iwx_node *);
 int    iwx_rs_init_v4(struct iwx_softc *, struct iwx_node *);
 int    iwx_rs_init(struct iwx_softc *, struct iwx_node *);
 int    iwx_enable_data_tx_queues(struct iwx_softc *);
+int    iwx_phy_send_rlc(struct iwx_softc *, struct iwx_phy_ctxt *,
+           uint8_t, uint8_t);
 int    iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *,
            struct ieee80211_channel *, uint8_t, uint8_t, uint32_t, uint8_t,
            uint8_t);
@@ -5505,13 +5507,17 @@ iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
                cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
        }
 
-       idle_cnt = chains_static;
-       active_cnt = chains_dynamic;
-       cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
-           IWX_PHY_RX_CHAIN_VALID_POS);
-       cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
-       cmd.rxchain_info |= htole32(active_cnt <<
-           IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
+       if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
+           IWX_RLC_CONFIG_CMD) != 2) {
+               idle_cnt = chains_static;
+               active_cnt = chains_dynamic;
+               cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
+                   IWX_PHY_RX_CHAIN_VALID_POS);
+               cmd.rxchain_info |= htole32(idle_cnt <<
+                   IWX_PHY_RX_CHAIN_CNT_POS);
+               cmd.rxchain_info |= htole32(active_cnt <<
+                   IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
+       }
 
        return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
 }
@@ -5561,13 +5567,17 @@ iwx_phy_ctxt_cmd_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
                cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
        }
 
-       idle_cnt = chains_static;
-       active_cnt = chains_dynamic;
-       cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
-           IWX_PHY_RX_CHAIN_VALID_POS);
-       cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
-       cmd.rxchain_info |= htole32(active_cnt <<
-           IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
+       if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
+           IWX_RLC_CONFIG_CMD) != 2) {
+               idle_cnt = chains_static;
+               active_cnt = chains_dynamic;
+               cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
+                   IWX_PHY_RX_CHAIN_VALID_POS);
+               cmd.rxchain_info |= htole32(idle_cnt <<
+                   IWX_PHY_RX_CHAIN_CNT_POS);
+               cmd.rxchain_info |= htole32(active_cnt <<
+                   IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
+       }
 
        return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
 }
@@ -7856,6 +7866,30 @@ iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif)
        }
 }
 
+int
+iwx_phy_send_rlc(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt,
+    uint8_t chains_static, uint8_t chains_dynamic)
+{
+       struct iwx_rlc_config_cmd cmd;
+       uint32_t cmd_id;
+       uint8_t active_cnt, idle_cnt;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       idle_cnt = chains_static;
+       active_cnt = chains_dynamic;
+
+       cmd.phy_id = htole32(phyctxt->id),
+       cmd.rlc.rx_chain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
+           IWX_PHY_RX_CHAIN_VALID_POS);
+       cmd.rlc.rx_chain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
+       cmd.rlc.rx_chain_info |= htole32(active_cnt <<
+           IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
+
+       cmd_id = iwx_cmd_id(IWX_RLC_CONFIG_CMD, IWX_DATA_PATH_GROUP, 2);
+       return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
+}
+
 int
 iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt,
     struct ieee80211_channel *chan, uint8_t chains_static,
@@ -7900,6 +7934,12 @@ iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt,
 
        phyctxt->sco = sco;
        phyctxt->vht_chan_width = vht_chan_width;
+
+       if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
+           IWX_RLC_CONFIG_CMD) == 2)
+               return iwx_phy_send_rlc(sc, phyctxt,
+                   chains_static, chains_dynamic);
+
        return 0;
 }
 
@@ -8865,6 +8905,15 @@ iwx_init_hw(struct iwx_softc *sc)
                            DEVNAME(sc), i, err);
                        goto err;
                }
+               if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
+                   IWX_RLC_CONFIG_CMD) == 2) {
+                       err = iwx_phy_send_rlc(sc, &sc->sc_phyctxt[i], 1, 1);
+                       if (err) {
+                               printf("%s: could not configure RLC for PHY "
+                                   "%d (error %d)\n", DEVNAME(sc), i, err);
+                               goto err;
+                       }
+               }
        }
 
        err = iwx_config_ltr(sc);
@@ -9907,6 +9956,9 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml)
                        break;
                }
 
+               case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_RLC_CONFIG_CMD):
+                       break;
+
                case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
                    IWX_PNVM_INIT_COMPLETE):
                        sc->sc_init_complete |= IWX_PNVM_COMPLETE;
index daa6489..fc8ef44 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwxreg.h,v 1.46 2023/03/06 10:48:05 stsp Exp $     */
+/*     $OpenBSD: if_iwxreg.h,v 1.47 2023/03/06 10:52:16 stsp Exp $     */
 
 /*-
  * Based on BSD-licensed source modules in the Linux iwlwifi driver,
@@ -2004,6 +2004,7 @@ struct iwx_tx_queue_cfg_rsp {
 
 /* DATA_PATH group subcommand IDs */
 #define IWX_DQA_ENABLE_CMD     0x00
+#define IWX_RLC_CONFIG_CMD     0x08
 #define IWX_TLC_MNG_CONFIG_CMD 0x0f
 #define IWX_RX_NO_DATA_NOTIF   0xf5
 #define IWX_TLC_MNG_UPDATE_NOTIF 0xf7
@@ -5272,6 +5273,60 @@ enum {
 #define IWX_LQ_FLAG_DYNAMIC_BW_POS          6
 #define IWX_LQ_FLAG_DYNAMIC_BW_MSK          (1 << IWX_LQ_FLAG_DYNAMIC_BW_POS)
 
+#define IWX_RLC_CHAIN_INFO_DRIVER_FORCE                (1 << 0)
+#define IWL_RLC_CHAIN_INFO_VALID               0x000e
+#define IWL_RLC_CHAIN_INFO_FORCE               0x0070
+#define IWL_RLC_CHAIN_INFO_FORCE_MIMO          0x0380
+#define IWL_RLC_CHAIN_INFO_COUNT               0x0c00
+#define IWL_RLC_CHAIN_INFO_MIMO_COUNT          0x3000
+
+/**
+ * struct iwx_rlc_properties - RLC properties
+ * @rx_chain_info: RX chain info, IWX_RLC_CHAIN_INFO_*
+ * @reserved: reserved
+ */
+struct iwx_rlc_properties {
+       uint32_t rx_chain_info;
+       uint32_t reserved;
+} __packed; /* RLC_PROPERTIES_S_VER_1 */
+
+#define IWX_SAD_MODE_ENABLED           (1 << 0)
+#define IWX_SAD_MODE_DEFAULT_ANT_MSK   0x6
+#define IWX_SAD_MODE_DEFAULT_ANT_FW    0x0
+#define IWX_SAD_MODE_DEFAULT_ANT_A     0x2
+#define IWX_SAD_MODE_DEFAULT_ANT_B     0x4
+
+/**
+ * struct iwx_sad_properties - SAD properties
+ * @chain_a_sad_mode: chain A SAD mode, IWX_SAD_MODE_*
+ * @chain_b_sad_mode: chain B SAD mode, IWX_SAD_MODE_*
+ * @mac_id: MAC index
+ * @reserved: reserved
+ */
+struct iwx_sad_properties {
+       uint32_t chain_a_sad_mode;
+       uint32_t chain_b_sad_mode;
+       uint32_t mac_id;
+       uint32_t reserved;
+} __packed;
+
+/**
+ * struct iwx_rlc_config_cmd - RLC configuration
+ * @phy_id: PHY index
+ * @rlc: RLC properties, &struct iwx_rlc_properties
+ * @sad: SAD (single antenna diversity) options, &struct iwx_sad_properties
+ * @flags: flags, IWX_RLC_FLAGS_*
+ * @reserved: reserved
+ */
+struct iwx_rlc_config_cmd {
+       uint32_t phy_id;
+       struct iwx_rlc_properties rlc;
+       struct iwx_sad_properties sad;
+       uint8_t flags;
+       uint8_t reserved[3];
+} __packed; /* RLC_CONFIG_CMD_API_S_VER_2 */
+
+
 /**
  * Options for TLC config flags
  * @IWX_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC. For HE this enables STBC for