Merge tag 'wireless-drivers-next-2020-05-07' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / drivers / net / wireless / intel / iwlwifi / mvm / fw.c
index e67c452..164fc9e 100644 (file)
@@ -102,9 +102,23 @@ static int iwl_set_soc_latency(struct iwl_mvm *mvm)
        if (!mvm->trans->trans_cfg->integrated)
                cmd.flags = cpu_to_le32(SOC_CONFIG_CMD_FLAGS_DISCRETE);
 
-       if (iwl_mvm_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
-                                  SCAN_REQ_UMAC) >= 2 &&
-           (mvm->trans->trans_cfg->low_latency_xtal))
+       BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_NONE !=
+                    SOC_FLAGS_LTR_APPLY_DELAY_NONE);
+       BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_200US !=
+                    SOC_FLAGS_LTR_APPLY_DELAY_200);
+       BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_2500US !=
+                    SOC_FLAGS_LTR_APPLY_DELAY_2500);
+       BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_1820US !=
+                    SOC_FLAGS_LTR_APPLY_DELAY_1820);
+
+       if (mvm->trans->trans_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE &&
+           !WARN_ON(!mvm->trans->trans_cfg->integrated))
+               cmd.flags |= le32_encode_bits(mvm->trans->trans_cfg->ltr_delay,
+                                             SOC_FLAGS_LTR_APPLY_DELAY_MASK);
+
+       if (iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
+                                 SCAN_REQ_UMAC) >= 2 &&
+           mvm->trans->trans_cfg->low_latency_xtal)
                cmd.flags |= cpu_to_le32(SOC_CONFIG_CMD_FLAGS_LOW_LATENCY);
 
        cmd.latency = cpu_to_le32(mvm->trans->trans_cfg->xtal_latency);
@@ -550,10 +564,49 @@ error:
        return ret;
 }
 
+#ifdef CONFIG_ACPI
+static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
+                                   struct iwl_phy_specific_cfg *phy_filters)
+{
+       /*
+        * TODO: read specific phy config from BIOS
+        * ACPI table for this feature has not been defined yet,
+        * so for now we use hardcoded values.
+        */
+
+       if (IWL_MVM_PHY_FILTER_CHAIN_A) {
+               phy_filters->filter_cfg_chain_a =
+                       cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A);
+       }
+       if (IWL_MVM_PHY_FILTER_CHAIN_B) {
+               phy_filters->filter_cfg_chain_b =
+                       cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B);
+       }
+       if (IWL_MVM_PHY_FILTER_CHAIN_C) {
+               phy_filters->filter_cfg_chain_c =
+                       cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C);
+       }
+       if (IWL_MVM_PHY_FILTER_CHAIN_D) {
+               phy_filters->filter_cfg_chain_d =
+                       cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
+       }
+}
+
+#else /* CONFIG_ACPI */
+
+static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
+                                   struct iwl_phy_specific_cfg *phy_filters)
+{
+}
+#endif /* CONFIG_ACPI */
+
 static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
 {
-       struct iwl_phy_cfg_cmd phy_cfg_cmd;
+       struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
        enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
+       struct iwl_phy_specific_cfg phy_filters = {};
+       u8 cmd_ver;
+       size_t cmd_size;
 
        if (iwl_mvm_has_unified_ucode(mvm) &&
            !mvm->trans->cfg->tx_with_siso_diversity)
@@ -580,11 +633,20 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
        phy_cfg_cmd.calib_control.flow_trigger =
                mvm->fw->default_calib[ucode_type].flow_trigger;
 
+       cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
+                                       PHY_CONFIGURATION_CMD);
+       if (cmd_ver == 3) {
+               iwl_mvm_phy_filter_init(mvm, &phy_filters);
+               memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters,
+                      sizeof(struct iwl_phy_specific_cfg));
+       }
+
        IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
                       phy_cfg_cmd.phy_cfg);
-
+       cmd_size = (cmd_ver == 3) ? sizeof(struct iwl_phy_cfg_cmd_v3) :
+                                   sizeof(struct iwl_phy_cfg_cmd_v1);
        return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0,
-                                   sizeof(phy_cfg_cmd), &phy_cfg_cmd);
+                                   cmd_size, &phy_cfg_cmd);
 }
 
 int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
@@ -937,6 +999,40 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
        return iwl_mvm_ppag_send_cmd(mvm);
 }
 
+static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
+{
+       int ret;
+       struct iwl_tas_config_cmd cmd = {};
+       int list_size;
+
+       BUILD_BUG_ON(ARRAY_SIZE(cmd.black_list_array) <
+                    APCI_WTAS_BLACK_LIST_MAX);
+
+       if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TAS_CFG)) {
+               IWL_DEBUG_RADIO(mvm, "TAS not enabled in FW\n");
+               return;
+       }
+
+       ret = iwl_acpi_get_tas(&mvm->fwrt, cmd.black_list_array, &list_size);
+       if (ret < 0) {
+               IWL_DEBUG_RADIO(mvm,
+                               "TAS table invalid or unavailable. (%d)\n",
+                               ret);
+               return;
+       }
+
+       if (list_size < 0)
+               return;
+
+       /* list size if TAS enabled can only be non-negative */
+       cmd.black_list_size = cpu_to_le32((u32)list_size);
+
+       ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
+                                               TAS_CONFIG),
+                                  0, sizeof(cmd), &cmd);
+       if (ret < 0)
+               IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
+}
 #else /* CONFIG_ACPI */
 
 inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm,
@@ -964,6 +1060,10 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
 {
        return 0;
 }
+
+static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
+{
+}
 #endif /* CONFIG_ACPI */
 
 void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
@@ -1282,6 +1382,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
        if (ret < 0)
                goto error;
 
+       iwl_mvm_tas_init(mvm);
        iwl_mvm_leds_sync(mvm);
 
        IWL_DEBUG_INFO(mvm, "RT uCode started.\n");