Commit b43310e4 authored by Govindaraj Saminathan's avatar Govindaraj Saminathan Committed by Kalle Valo
Browse files

wifi: ath11k: factory test mode support



Add support to process factory test mode commands (FTM) for calibration.
By default firmware start with NORMAL mode and to process the FTM commands
firmware needs to be restarted in FTM mode using module parameter ftm_mode.
The pre-request is all the radios should be down before starting the test.

When start command ATH11K_TM_CMD_TESTMODE_START is received, ar->state
is set to Test Mode. If the FTM command or event length is greater
than 256 bytes, it will be broken down into multiple segments and
encoded with TLV header if it is segmented commands, else it is sent
to firmware as it is.

On receiving UTF event from firmware, if it is segmented event, the driver
will wait until it receives all the segments and notify the complete
data to user application. In case the segmented sequence are missed or
lost from the firmware, driver will skip the already received partial data.

In case of unsegmented UTF event from firmware, driver notifies the
data to the user application as it comes. Applications handles
the data further.

Command to boot in ftm mode:

insmod ath11k ftm_mode=1

Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1

Signed-off-by: default avatarGovindaraj Saminathan <quic_gsaminat@quicinc.com>
Co-developed-by: default avatarSowmiya Sree Elavalagan <quic_ssreeela@quicinc.com>
Signed-off-by: default avatarSowmiya Sree Elavalagan <quic_ssreeela@quicinc.com>
Signed-off-by: default avatarRaj Kumar Bhagat <quic_rajkbhag@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230517135934.16408-4-quic_rajkbhag@quicinc.com
parent 86f85575
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/module.h>
@@ -1155,6 +1155,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
	ab->hif.ops = hif_ops;
	ab->pdev = pdev;
	ab->hw_rev = hw_rev;
	ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
	platform_set_drvdata(pdev, ab);

	ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
+18 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/module.h>
@@ -32,6 +32,10 @@ module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
		 "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");

bool ath11k_ftm_mode;
module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");

static const struct ath11k_hw_params ath11k_hw_params[] = {
	{
		.hw_rev = ATH11K_HW_IPQ8074,
@@ -1381,6 +1385,11 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
{
	int ret;

	if (ath11k_ftm_mode) {
		ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM;
		ath11k_info(ab, "Booting in factory test mode\n");
	}

	ret = ath11k_qmi_init_service(ab);
	if (ret) {
		ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
@@ -1607,7 +1616,7 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
{
	int ret;

	ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL);
	ret = ath11k_core_start_firmware(ab, ab->fw_mode);
	if (ret) {
		ath11k_err(ab, "failed to start firmware: %d\n", ret);
		return ret;
@@ -1772,7 +1781,8 @@ void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
	for (i = 0; i < ab->num_radios; i++) {
		pdev = &ab->pdevs[i];
		ar = pdev->ar;
		if (!ar || ar->state == ATH11K_STATE_OFF)
		if (!ar || ar->state == ATH11K_STATE_OFF ||
		    ar->state == ATH11K_STATE_FTM)
			continue;

		ieee80211_stop_queues(ar->hw);
@@ -1841,7 +1851,12 @@ static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)
			ath11k_warn(ab,
				    "device is wedged, will not restart radio %d\n", i);
			break;
		case ATH11K_STATE_FTM:
			ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
				   "fw mode reset done radio %d\n", i);
			break;
		}

		mutex_unlock(&ar->conf_mutex);
	}
	complete(&ab->driver_recovery);
+15 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#ifndef ATH11K_CORE_H
@@ -52,6 +52,7 @@
#define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_"

extern unsigned int ath11k_frame_mode;
extern bool ath11k_ftm_mode;

#define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ)

@@ -277,6 +278,7 @@ enum ath11k_dev_flags {
	ATH11K_FLAG_FIXED_MEM_RGN,
	ATH11K_FLAG_DEVICE_INIT_DONE,
	ATH11K_FLAG_MULTI_MSI_VECTORS,
	ATH11K_FLAG_FTM_SEGMENTED,
};

enum ath11k_monitor_flags {
@@ -530,6 +532,7 @@ enum ath11k_state {
	ATH11K_STATE_RESTARTING,
	ATH11K_STATE_RESTARTED,
	ATH11K_STATE_WEDGED,
	ATH11K_STATE_FTM,
	/* Add other states as required */
};

@@ -709,6 +712,8 @@ struct ath11k {
	u32 last_ppdu_id;
	u32 cached_ppdu_id;
	int monitor_vdev_id;
	struct completion fw_mode_reset;
	u8 ftm_msgref;
#ifdef CONFIG_ATH11K_DEBUGFS
	struct ath11k_debug debug;
#endif
@@ -838,6 +843,7 @@ struct ath11k_msi_config {
/* Master structure to hold the hw data which may be used in core module */
struct ath11k_base {
	enum ath11k_hw_rev hw_rev;
	enum ath11k_firmware_mode fw_mode;
	struct platform_device *pdev;
	struct device *dev;
	struct ath11k_qmi qmi;
@@ -978,6 +984,14 @@ struct ath11k_base {
		const struct ath11k_pci_ops *ops;
	} pci;

#ifdef CONFIG_NL80211_TESTMODE
	struct {
		u32 data_pos;
		u32 expected_seq;
		u8 *eventdata;
	} testmode;
#endif

	/* must be last */
	u8 drv_priv[] __aligned(sizeof(void *));
};
+1 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#ifndef _ATH11K_DEBUG_H_
+10 −1
Original line number Diff line number Diff line
@@ -643,6 +643,9 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
		return NULL;

	for (i = 0; i < ab->num_radios; i++) {
		if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
			pdev = &ab->pdevs[i];
		else
			pdev = rcu_dereference(ab->pdevs_active[i]);

		if (pdev && pdev->pdev_id == pdev_id)
@@ -6271,6 +6274,11 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
	struct ath11k_pdev *pdev = ar->pdev;
	int ret;

	if (ath11k_ftm_mode) {
		ath11k_warn(ab, "mac operations not supported in factory test mode\n");
		return -EOPNOTSUPP;
	}

	ath11k_mac_drain_tx(ar);
	mutex_lock(&ar->conf_mutex);

@@ -6285,6 +6293,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
	case ATH11K_STATE_RESTARTED:
	case ATH11K_STATE_WEDGED:
	case ATH11K_STATE_ON:
	case ATH11K_STATE_FTM:
		WARN_ON(1);
		ret = -EINVAL;
		goto err;
Loading