ath10k: skip sending quiet mode cmd for WCN3990
authorRakesh Pillai <pillair@codeaurora.org>
Fri, 14 Dec 2018 10:17:46 +0000 (12:17 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 19 Dec 2018 13:37:01 +0000 (15:37 +0200)
HL2.0 firmware does not support setting quiet mode.  If the host driver sends
the quiet mode setting command to the HL2.0 firmware, it crashes with the below
signature.

fatal error received: err_qdi.c:456:EX:wlan_process:1:WLAN RT:207a:PC=b001b4f0

The quiet mode command support is exposed by the firmware via thermal throttle
wmi service. Enable ath10k thermal support if thermal throttle wmi service bit
is set.  10.x firmware versions support this feature by default, but
unfortunately do not advertise the support via service flags, hence have to
manually set the service flag in ath10k_core_compat_services().

Tested on QCA988X with 10.2.4.70.9-2. Also tested on WCN3990.

Co-developed-by: Govind Singh <govinds@codeaurora.org>
Co-developed-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
Signed-off-by: Govind Singh <govinds@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/thermal.c
drivers/net/wireless/ath/ath10k/wmi-tlv.h
drivers/net/wireless/ath/ath10k/wmi.h

index da607febfd8200fffbdd5cfa575866a7f99cd04b..d210b0ed59beb606bdef977ae0bec7babd00f212 100644 (file)
@@ -2418,6 +2418,28 @@ static int ath10k_core_reset_rx_filter(struct ath10k *ar)
        return 0;
 }
 
+static int ath10k_core_compat_services(struct ath10k *ar)
+{
+       struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
+
+       /* all 10.x firmware versions support thermal throttling but don't
+        * advertise the support via service flags so we have to hardcode
+        * it here
+        */
+       switch (fw_file->wmi_op_version) {
+       case ATH10K_FW_WMI_OP_VERSION_10_1:
+       case ATH10K_FW_WMI_OP_VERSION_10_2:
+       case ATH10K_FW_WMI_OP_VERSION_10_2_4:
+       case ATH10K_FW_WMI_OP_VERSION_10_4:
+               set_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
                      const struct ath10k_fw_components *fw)
 {
@@ -2617,6 +2639,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
                goto err_hif_stop;
        }
 
+       status = ath10k_core_compat_services(ar);
+       if (status) {
+               ath10k_err(ar, "compat services failed: %d\n", status);
+               goto err_hif_stop;
+       }
+
        /* Some firmware revisions do not properly set up hardware rx filter
         * registers.
         *
index 15964b374f68da69636e256d6a3911cc3eee773b..02988fc378a1581844645661349bdfdfcf3d3993 100644 (file)
@@ -2578,8 +2578,9 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("pktlog_filter", 0644, ar->debug.debugfs_phy, ar,
                            &fops_pktlog_filter);
 
-       debugfs_create_file("quiet_period", 0644, ar->debug.debugfs_phy, ar,
-                           &fops_quiet_period);
+       if (test_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map))
+               debugfs_create_file("quiet_period", 0644, ar->debug.debugfs_phy, ar,
+                                   &fops_quiet_period);
 
        debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_phy, ar,
                            &fops_tpc_stats);
index aa8978a8d7514aa5f827ff6de9d4465ffee9a334..fe35edcd3ec8104005310f5c831218493d990754 100644 (file)
@@ -140,6 +140,9 @@ void ath10k_thermal_set_throttling(struct ath10k *ar)
 
        lockdep_assert_held(&ar->conf_mutex);
 
+       if (!test_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map))
+               return;
+
        if (!ar->wmi.ops->gen_pdev_set_quiet_mode)
                return;
 
@@ -165,6 +168,9 @@ int ath10k_thermal_register(struct ath10k *ar)
        struct device *hwmon_dev;
        int ret;
 
+       if (!test_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map))
+               return 0;
+
        cdev = thermal_cooling_device_register("ath10k_thermal", ar,
                                               &ath10k_thermal_ops);
 
@@ -216,6 +222,9 @@ err_cooling_destroy:
 
 void ath10k_thermal_unregister(struct ath10k *ar)
 {
+       if (!test_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map))
+               return;
+
        sysfs_remove_link(&ar->dev->kobj, "cooling_device");
        thermal_cooling_device_unregister(ar->thermal.cdev);
 }
index 92c25f51bf868fd8daa4d93b0d7e4b888125ffc2..c2cb413392eeb350fd146ab585178b38768eeecf 100644 (file)
@@ -1564,6 +1564,9 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
        SVCMAP(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT,
               WMI_SERVICE_SPOOF_MAC_SUPPORT,
               WMI_TLV_MAX_SERVICE);
+       SVCMAP(WMI_TLV_SERVICE_THERM_THROT,
+              WMI_SERVICE_THERM_THROT,
+              WMI_TLV_MAX_SERVICE);
 }
 
 #undef SVCMAP
index f7badd079051d35601ca1fa6400601d4109604ad..c5a343c93013132d613acae897a5511339c1b94a 100644 (file)
@@ -205,6 +205,7 @@ enum wmi_service {
        WMI_SERVICE_SPOOF_MAC_SUPPORT,
        WMI_SERVICE_TX_DATA_ACK_RSSI,
        WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+       WMI_SERVICE_THERM_THROT,
 
        /* keep last */
        WMI_SERVICE_MAX,