Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43d2a30f authored by Kalle Valo's avatar Kalle Valo
Browse files

ath10k: add testmode



Add testmode interface for starting and using UTF firmware which is used to run
factory tests. This is implemented by adding new state ATH10K_STATE_UTF and user
space can enable this state with ATH10K_TM_CMD_UTF_START command. To go back to
normal mode user space can send ATH10K_TM_CMD_UTF_STOP.

Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 666a73f3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ ath10k_core-y += mac.o \
		 bmi.o

ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o

obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
+62 −26
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "bmi.h"
#include "debug.h"
#include "htt.h"
#include "testmode.h"

unsigned int ath10k_debug_mask;
static bool uart_print;
@@ -257,21 +258,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
	return 0;
}

static int ath10k_download_fw(struct ath10k *ar)
static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
	u32 address;
	u32 address, data_len;
	const char *mode_name;
	const void *data;
	int ret;

	address = ar->hw_params.patch_load_addr;

	ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
				       ar->firmware_len);
	switch (mode) {
	case ATH10K_FIRMWARE_MODE_NORMAL:
		data = ar->firmware_data;
		data_len = ar->firmware_len;
		mode_name = "normal";
		break;
	case ATH10K_FIRMWARE_MODE_UTF:
		data = ar->testmode.utf->data;
		data_len = ar->testmode.utf->size;
		mode_name = "utf";
		break;
	default:
		ath10k_err(ar, "unknown firmware mode: %d\n", mode);
		return -EINVAL;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
		   "boot uploading firmware image %p len %d mode %s\n",
		   data, data_len, mode_name);

	ret = ath10k_bmi_fast_download(ar, address, data, data_len);
	if (ret) {
		ath10k_err(ar, "could not write fw (%d)\n", ret);
		goto exit;
		ath10k_err(ar, "failed to download %s firmware: %d\n",
			   mode_name, ret);
		return ret;
	}

exit:
	return ret;
}

@@ -567,7 +589,8 @@ success:
	return 0;
}

static int ath10k_init_download_firmware(struct ath10k *ar)
static int ath10k_init_download_firmware(struct ath10k *ar,
					 enum ath10k_firmware_mode mode)
{
	int ret;

@@ -583,7 +606,7 @@ static int ath10k_init_download_firmware(struct ath10k *ar)
		return ret;
	}

	ret = ath10k_download_fw(ar);
	ret = ath10k_download_fw(ar, mode);
	if (ret) {
		ath10k_err(ar, "failed to download firmware: %d\n", ret);
		return ret;
@@ -685,12 +708,15 @@ static void ath10k_core_restart(struct work_struct *work)
	case ATH10K_STATE_WEDGED:
		ath10k_warn(ar, "device is wedged, will not restart\n");
		break;
	case ATH10K_STATE_UTF:
		ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
		break;
	}

	mutex_unlock(&ar->conf_mutex);
}

int ath10k_core_start(struct ath10k *ar)
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
	int status;

@@ -703,7 +729,7 @@ int ath10k_core_start(struct ath10k *ar)
		goto err;
	}

	status = ath10k_init_download_firmware(ar);
	status = ath10k_init_download_firmware(ar, mode);
	if (status)
		goto err;

@@ -760,11 +786,13 @@ int ath10k_core_start(struct ath10k *ar)
		goto err_hif_stop;
	}

	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
		status = ath10k_htt_connect(&ar->htt);
		if (status) {
			ath10k_err(ar, "failed to connect htt (%d)\n", status);
			goto err_hif_stop;
		}
	}

	status = ath10k_wmi_connect(ar);
	if (status) {
@@ -778,12 +806,14 @@ int ath10k_core_start(struct ath10k *ar)
		goto err_hif_stop;
	}

	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
		status = ath10k_wmi_wait_for_service_ready(ar);
		if (status <= 0) {
			ath10k_warn(ar, "wmi service ready event not received");
			status = -ETIMEDOUT;
			goto err_hif_stop;
		}
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
		   ar->hw->wiphy->fw_version);
@@ -802,11 +832,14 @@ int ath10k_core_start(struct ath10k *ar)
		goto err_hif_stop;
	}

	/* we don't care about HTT in UTF mode */
	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
		status = ath10k_htt_setup(&ar->htt);
		if (status) {
			ath10k_err(ar, "failed to setup htt: %d\n", status);
			goto err_hif_stop;
		}
	}

	status = ath10k_debug_start(ar);
	if (status)
@@ -861,7 +894,8 @@ void ath10k_core_stop(struct ath10k *ar)
	lockdep_assert_held(&ar->conf_mutex);

	/* try to suspend target */
	if (ar->state != ATH10K_STATE_RESTARTING)
	if (ar->state != ATH10K_STATE_RESTARTING &&
	    ar->state != ATH10K_STATE_UTF)
		ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);

	ath10k_debug_stop(ar);
@@ -914,7 +948,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)

	mutex_lock(&ar->conf_mutex);

	ret = ath10k_core_start(ar);
	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
	if (ret) {
		ath10k_err(ar, "could not init core (%d)\n", ret);
		ath10k_core_free_firmware_files(ar);
@@ -1041,6 +1075,8 @@ void ath10k_core_unregister(struct ath10k *ar)
	 * unhappy about callback failures. */
	ath10k_mac_unregister(ar);

	ath10k_testmode_destroy(ar);

	ath10k_core_free_firmware_files(ar);

	ath10k_debug_unregister(ar);
+21 −1
Original line number Diff line number Diff line
@@ -330,6 +330,17 @@ enum ath10k_state {
	 * prevents completion timeouts and makes the driver more responsive to
	 * userspace commands. This is also prevents recursive recovery. */
	ATH10K_STATE_WEDGED,

	/* factory tests */
	ATH10K_STATE_UTF,
};

enum ath10k_firmware_mode {
	/* the default mode, standard 802.11 functionality */
	ATH10K_FIRMWARE_MODE_NORMAL,

	/* factory tests etc */
	ATH10K_FIRMWARE_MODE_UTF,
};

enum ath10k_fw_features {
@@ -543,6 +554,15 @@ struct ath10k {
		struct ath10k_spec_scan config;
	} spectral;

	struct {
		/* protected by conf_mutex */
		const struct firmware *utf;
		DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);

		/* protected by data_lock */
		bool utf_monitor;
	} testmode;

	/* must be last */
	u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -551,7 +571,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
				  const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar);

int ath10k_core_start(struct ath10k *ar);
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar, u32 chip_id);
+3 −2
Original line number Diff line number Diff line
@@ -134,11 +134,12 @@ void ath10k_print_driver_info(struct ath10k *ar)
		    ar->fw_api,
		    ar->htt.target_version_major,
		    ar->htt.target_version_minor);
	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d\n",
	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
		    config_enabled(CONFIG_ATH10K_DEBUG),
		    config_enabled(CONFIG_ATH10K_DEBUGFS),
		    config_enabled(CONFIG_ATH10K_TRACING),
		    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
		    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
		    config_enabled(CONFIG_NL80211_TESTMODE));
}
EXPORT_SYMBOL(ath10k_print_driver_info);

+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ enum ath10k_debug_mask {
	ATH10K_DBG_DATA		= 0x00000200,
	ATH10K_DBG_BMI		= 0x00000400,
	ATH10K_DBG_REGULATORY	= 0x00000800,
	ATH10K_DBG_TESTMODE	= 0x00001000,
	ATH10K_DBG_ANY		= 0xffffffff,
};

Loading