@@ -2927,6 +2927,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
int status;
u32 val;
+ if (ar->is_started && ar->hw_params.start_once)
+ return 0;
+
lockdep_assert_held(&ar->conf_mutex);
clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -3231,6 +3234,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_hif_stop;
}
+ ar->is_started = true;
+
return 0;
err_hif_stop:
@@ -3285,6 +3290,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_wmi_detach(ar);
ar->id.bmi_ids_valid = false;
+ ar->is_started = false;
}
EXPORT_SYMBOL(ath10k_core_stop);
@@ -3424,12 +3430,18 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_unlock;
}
- ath10k_debug_print_boot_info(ar);
- ath10k_core_stop(ar);
+ /* Leave target running if hw_params.start_once is set */
+ if (ar->hw_params.start_once) {
+ mutex_unlock(&ar->conf_mutex);
+ } else {
+ ath10k_debug_print_boot_info(ar);
+ ath10k_core_stop(ar);
+
+ mutex_unlock(&ar->conf_mutex);
- mutex_unlock(&ar->conf_mutex);
+ ath10k_hif_power_down(ar);
+ }
- ath10k_hif_power_down(ar);
return 0;
err_unlock:
@@ -1054,6 +1054,8 @@ struct ath10k {
bool nlo_enabled;
bool p2p;
+ bool is_started;
+
struct {
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
@@ -639,6 +639,12 @@ struct ath10k_hw_params {
bool use_fw_tx_credits;
bool delay_unmap_buffer;
+
+ /* Specifies whether or not the device should be started once.
+ * If set, the device will be started once by the early fw probe
+ * and it will not be terminated afterwards.
+ */
+ bool start_once;
};
struct htt_resp;
@@ -4790,8 +4790,11 @@ void ath10k_halt(struct ath10k *ar)
ath10k_scan_finish(ar);
ath10k_peer_cleanup_all(ar);
ath10k_stop_radar_confirmation(ar);
- ath10k_core_stop(ar);
- ath10k_hif_power_down(ar);
+ /* Leave target running if hw_params.start_once is set */
+ if (!ar->hw_params.start_once) {
+ ath10k_core_stop(ar);
+ ath10k_hif_power_down(ar);
+ }
spin_lock_bh(&ar->data_lock);
list_for_each_entry(arvif, &ar->arvifs, list)