示例#1
0
static int ath10k_init_uart(struct ath10k *ar)
{
	int ret;

	/*
	 * Explicitly setting UART prints to zero as target turns it on
	 * based on scratch registers.
	 */
	ret = ath10k_bmi_write32(ar, hi_serial_enable, 0);
	if (ret) {
		ath10k_warn("could not disable UART prints (%d)\n", ret);
		return ret;
	}

	if (!uart_print) {
		ath10k_info("UART prints disabled\n");
		return 0;
	}

	ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
	if (ret) {
		ath10k_warn("could not enable UART prints (%d)\n", ret);
		return ret;
	}

	ret = ath10k_bmi_write32(ar, hi_serial_enable, 1);
	if (ret) {
		ath10k_warn("could not enable UART prints (%d)\n", ret);
		return ret;
	}

	ath10k_info("UART prints enabled\n");
	return 0;
}
示例#2
0
/* Simulate firmware crash:
 * 'soft': Call wmi command causing firmware hang. This firmware hang is
 * recoverable by warm firmware reset.
 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
 * vdev id. This is hard firmware crash because it is recoverable only by cold
 * firmware reset.
 */
static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
					      const char __user *user_buf,
					      size_t count, loff_t *ppos)
{
	struct ath10k *ar = file->private_data;
	char buf[32];
	int ret;

	mutex_lock(&ar->conf_mutex);

	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);

	/* make sure that buf is null terminated */
	buf[sizeof(buf) - 1] = 0;

	if (ar->state != ATH10K_STATE_ON &&
	    ar->state != ATH10K_STATE_RESTARTED) {
		ret = -ENETDOWN;
		goto exit;
	}

	/* drop the possible '\n' from the end */
	if (buf[count - 1] == '\n') {
		buf[count - 1] = 0;
		count--;
	}

	if (!strcmp(buf, "soft")) {
		ath10k_info("simulating soft firmware crash\n");
		ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
	} else if (!strcmp(buf, "hard")) {
		ath10k_info("simulating hard firmware crash\n");
		ret = ath10k_wmi_vdev_set_param(ar, TARGET_NUM_VDEVS + 1,
					ar->wmi.vdev_param->rts_threshold, 0);
	} else {
		ret = -EINVAL;
		goto exit;
	}

	if (ret) {
		ath10k_warn("failed to simulate firmware crash: %d\n", ret);
		goto exit;
	}

	ret = count;

exit:
	mutex_unlock(&ar->conf_mutex);
	return ret;
}
示例#3
0
static int ath10k_core_fetch_board_file(struct ath10k *ar)
{
	int ret;

	if (strlen(ar->spec_board_id) > 0) {
		ret = ath10k_core_fetch_spec_board_file(ar);
		if (ret) {
			ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n",
				    ret);
			goto generic;
		}

		ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n",
			   ar->spec_board_id);
		return 0;
	}

generic:
	ret = ath10k_core_fetch_generic_board_file(ar);
	if (ret) {
		ath10k_err(ar, "failed to fetch generic board data: %d\n", ret);
		return ret;
	}

	return 0;
}
示例#4
0
static int ath10k_init_hw_params(struct ath10k *ar)
{
	const struct ath10k_hw_params *uninitialized_var(hw_params);
	int i;

	for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
		hw_params = &ath10k_hw_params_list[i];

		if (hw_params->id == ar->target_version)
			break;
	}

	if (i == ARRAY_SIZE(ath10k_hw_params_list)) {
		ath10k_err("Unsupported hardware version: 0x%x\n",
			   ar->target_version);
		return -EINVAL;
	}

	ar->hw_params = *hw_params;

	ath10k_info("Hardware name %s version 0x%x\n",
		    ar->hw_params.name, ar->target_version);

	return 0;
}
static int ath10k_htt_verify_version(struct ath10k_htt *htt)
{
	ath10k_info("htt target version %d.%d\n",
		    htt->target_version_major, htt->target_version_minor);

	if (htt->target_version_major != 2 &&
	    htt->target_version_major != 3) {
		ath10k_err("unsupported htt major version %d. supported versions are 2 and 3\n",
			   htt->target_version_major);
		return -ENOTSUPP;
	}

	return 0;
}
示例#6
0
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
	const struct firmware *fw;
	u32 address;
	u32 exec_param;
	int ret;

	/* OTP is optional */

	if (ar->hw_params.fw.otp == NULL) {
		ath10k_info("otp file not defined\n");
		return 0;
	}

	address = ar->hw_params.patch_load_addr;

	fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
				  ar->hw_params.fw.otp);
	if (IS_ERR(fw)) {
		ath10k_warn("could not fetch otp (%ld)\n", PTR_ERR(fw));
		return 0;
	}

	ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size);
	if (ret) {
		ath10k_err("could not write otp (%d)\n", ret);
		goto exit;
	}

	exec_param = 0;
	ret = ath10k_bmi_execute(ar, address, &exec_param);
	if (ret) {
		ath10k_err("could not execute otp (%d)\n", ret);
		goto exit;
	}

exit:
	release_firmware(fw);
	return ret;
}
示例#7
0
static int ath10k_init_uart(struct ath10k *ar)
{
	int ret;

	/*
	 * Explicitly setting UART prints to zero as target turns it on
	 * based on scratch registers.
	 */
	ret = ath10k_bmi_write32(ar, hi_serial_enable, 0);
	if (ret) {
		ath10k_warn(ar, "could not disable UART prints (%d)\n", ret);
		return ret;
	}

	if (!uart_print)
		return 0;

	ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin);
	if (ret) {
		ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
		return ret;
	}

	ret = ath10k_bmi_write32(ar, hi_serial_enable, 1);
	if (ret) {
		ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
		return ret;
	}

	/* Set the UART baud rate to 19200. */
	ret = ath10k_bmi_write32(ar, hi_desired_baud_rate, 19200);
	if (ret) {
		ath10k_warn(ar, "could not set the baud rate (%d)\n", ret);
		return ret;
	}

	ath10k_info(ar, "UART prints enabled\n");
	return 0;
}
示例#8
0
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
	if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
	    !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
		ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
		return -EINVAL;
	}

	if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
		ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",
			   ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version);
		return -EINVAL;
	}

	ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_NATIVE_WIFI;
	switch (ath10k_cryptmode_param) {
	case ATH10K_CRYPT_MODE_HW:
		clear_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
		clear_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
		break;
	case ATH10K_CRYPT_MODE_SW:
		if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
			      ar->fw_features)) {
			ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware");
			return -EINVAL;
		}

		set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
		set_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
		break;
	default:
		ath10k_info(ar, "invalid cryptmode: %d\n",
			    ath10k_cryptmode_param);
		return -EINVAL;
	}

	ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
	ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;

	if (rawmode) {
		if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
			      ar->fw_features)) {
			ath10k_err(ar, "rawmode = 1 requires support from firmware");
			return -EINVAL;
		}
		set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
	}

	if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
		ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;

		/* Workaround:
		 *
		 * Firmware A-MSDU aggregation breaks with RAW Tx encap mode
		 * and causes enormous performance issues (malformed frames,
		 * etc).
		 *
		 * Disabling A-MSDU makes RAW mode stable with heavy traffic
		 * albeit a bit slower compared to regular operation.
		 */
		ar->htt.max_num_amsdu = 1;
	}

	/* Backwards compatibility for firmwares without
	 * ATH10K_FW_IE_WMI_OP_VERSION.
	 */
	if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
		if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
			if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,
				     ar->fw_features))
				ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
			else
				ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
		} else {
			ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
		}
	}

	switch (ar->wmi.op_version) {
	case ATH10K_FW_WMI_OP_VERSION_MAIN:
		ar->max_num_peers = TARGET_NUM_PEERS;
		ar->max_num_stations = TARGET_NUM_STATIONS;
		ar->max_num_vdevs = TARGET_NUM_VDEVS;
		ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
		ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
			WMI_STAT_PEER;
		ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
		break;
	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:
		ar->max_num_peers = TARGET_10X_NUM_PEERS;
		ar->max_num_stations = TARGET_10X_NUM_STATIONS;
		ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
		ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
		ar->fw_stats_req_mask = WMI_STAT_PEER;
		ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
		break;
	case ATH10K_FW_WMI_OP_VERSION_TLV:
		ar->max_num_peers = TARGET_TLV_NUM_PEERS;
		ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
		ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
		ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
		ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
		ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS;
		ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
			WMI_STAT_PEER;
		ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
		break;
	case ATH10K_FW_WMI_OP_VERSION_10_4:
		ar->max_num_peers = TARGET_10_4_NUM_PEERS;
		ar->max_num_stations = TARGET_10_4_NUM_STATIONS;
		ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
		ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
		ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
		ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
		ar->fw_stats_req_mask = WMI_STAT_PEER;
		ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM;
		break;
	case ATH10K_FW_WMI_OP_VERSION_UNSET:
	case ATH10K_FW_WMI_OP_VERSION_MAX:
		WARN_ON(1);
		return -EINVAL;
	}

	/* Backwards compatibility for firmwares without
	 * ATH10K_FW_IE_HTT_OP_VERSION.
	 */
	if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) {
		switch (ar->wmi.op_version) {
		case ATH10K_FW_WMI_OP_VERSION_MAIN:
			ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN;
			break;
		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:
			ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
			break;
		case ATH10K_FW_WMI_OP_VERSION_TLV:
			ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
			break;
		case ATH10K_FW_WMI_OP_VERSION_10_4:
		case ATH10K_FW_WMI_OP_VERSION_UNSET:
		case ATH10K_FW_WMI_OP_VERSION_MAX:
			WARN_ON(1);
			return -EINVAL;
		}
	}

	return 0;
}
示例#9
0
int ath10k_core_start(struct ath10k *ar)
{
	int status;

	lockdep_assert_held(&ar->conf_mutex);

	ath10k_bmi_start(ar);

	if (ath10k_init_configure_target(ar)) {
		status = -EINVAL;
		goto err;
	}

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

	status = ath10k_init_uart(ar);
	if (status)
		goto err;

	ar->htc.htc_ops.target_send_suspend_complete =
		ath10k_send_suspend_complete;

	status = ath10k_htc_init(ar);
	if (status) {
		ath10k_err("could not init HTC (%d)\n", status);
		goto err;
	}

	status = ath10k_bmi_done(ar);
	if (status)
		goto err;

	status = ath10k_wmi_attach(ar);
	if (status) {
		ath10k_err("WMI attach failed: %d\n", status);
		goto err;
	}

	status = ath10k_hif_start(ar);
	if (status) {
		ath10k_err("could not start HIF: %d\n", status);
		goto err_wmi_detach;
	}

	status = ath10k_htc_wait_target(&ar->htc);
	if (status) {
		ath10k_err("failed to connect to HTC: %d\n", status);
		goto err_hif_stop;
	}

	status = ath10k_htt_attach(ar);
	if (status) {
		ath10k_err("could not attach htt (%d)\n", status);
		goto err_hif_stop;
	}

	status = ath10k_init_connect_htc(ar);
	if (status)
		goto err_htt_detach;

	ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
		   ar->hw->wiphy->fw_version);

	status = ath10k_wmi_cmd_init(ar);
	if (status) {
		ath10k_err("could not send WMI init command (%d)\n", status);
		goto err_disconnect_htc;
	}

	status = ath10k_wmi_wait_for_unified_ready(ar);
	if (status <= 0) {
		ath10k_err("wmi unified ready event not received\n");
		status = -ETIMEDOUT;
		goto err_disconnect_htc;
	}

	status = ath10k_htt_attach_target(&ar->htt);
	if (status)
		goto err_disconnect_htc;

	status = ath10k_debug_start(ar);
	if (status)
		goto err_disconnect_htc;

	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
	INIT_LIST_HEAD(&ar->arvifs);

	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
		ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n",
			    ar->hw_params.name, ar->target_version,
			    ar->hw->wiphy->fw_version, ar->fw_api,
			    ar->htt.target_version_major,
			    ar->htt.target_version_minor);

	__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);

	return 0;

err_disconnect_htc:
	ath10k_htc_stop(&ar->htc);
err_htt_detach:
	ath10k_htt_detach(&ar->htt);
err_hif_stop:
	ath10k_hif_stop(ar);
err_wmi_detach:
	ath10k_wmi_detach(ar);
err:
	return status;
}
示例#10
0
int ath10k_core_register(struct ath10k *ar)
{
	struct bmi_target_info target_info;
	int status;

	memset(&target_info, 0, sizeof(target_info));
	status = ath10k_bmi_get_target_info(ar, &target_info);
	if (status)
		goto err;

	ar->target_version = target_info.version;
	ar->hw->wiphy->hw_version = target_info.version;

	status = ath10k_init_hw_params(ar);
	if (status)
		goto err;

	if (ath10k_init_configure_target(ar)) {
		status = -EINVAL;
		goto err;
	}

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

	status = ath10k_init_uart(ar);
	if (status)
		goto err;

	ar->htc.htc_ops.target_send_suspend_complete =
		ath10k_send_suspend_complete;

	status = ath10k_htc_init(ar);
	if (status) {
		ath10k_err("could not init HTC (%d)\n", status);
		goto err;
	}

	status = ath10k_bmi_done(ar);
	if (status)
		goto err;

	status = ath10k_wmi_attach(ar);
	if (status) {
		ath10k_err("WMI attach failed: %d\n", status);
		goto err;
	}

	status = ath10k_htc_wait_target(&ar->htc);
	if (status)
		goto err_wmi_detach;

	status = ath10k_htt_attach(ar);
	if (status) {
		ath10k_err("could not attach htt (%d)\n", status);
		goto err_wmi_detach;
	}

	status = ath10k_init_connect_htc(ar);
	if (status)
		goto err_htt_detach;

	ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version);

	status = ath10k_check_fw_version(ar);
	if (status)
		goto err_disconnect_htc;

	status = ath10k_wmi_cmd_init(ar);
	if (status) {
		ath10k_err("could not send WMI init command (%d)\n", status);
		goto err_disconnect_htc;
	}

	status = ath10k_wmi_wait_for_unified_ready(ar);
	if (status <= 0) {
		ath10k_err("wmi unified ready event not received\n");
		status = -ETIMEDOUT;
		goto err_disconnect_htc;
	}

	status = ath10k_htt_attach_target(&ar->htt);
	if (status)
		goto err_disconnect_htc;

	status = ath10k_mac_register(ar);
	if (status)
		goto err_disconnect_htc;

	status = ath10k_debug_create(ar);
	if (status) {
		ath10k_err("unable to initialize debugfs\n");
		goto err_unregister_mac;
	}

	return 0;

err_unregister_mac:
	ath10k_mac_unregister(ar);
err_disconnect_htc:
	ath10k_htc_stop(&ar->htc);
err_htt_detach:
	ath10k_htt_detach(&ar->htt);
err_wmi_detach:
	ath10k_wmi_detach(ar);
err:
	return status;
}
示例#11
0
文件: core.c 项目: 03199618/linux
int ath10k_core_start(struct ath10k *ar)
{
	int status;

	ath10k_bmi_start(ar);

	if (ath10k_init_configure_target(ar)) {
		status = -EINVAL;
		goto err;
	}

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

	status = ath10k_init_uart(ar);
	if (status)
		goto err;

	ar->htc.htc_ops.target_send_suspend_complete =
		ath10k_send_suspend_complete;

	status = ath10k_htc_init(ar);
	if (status) {
		ath10k_err("could not init HTC (%d)\n", status);
		goto err;
	}

	status = ath10k_bmi_done(ar);
	if (status)
		goto err;

	status = ath10k_wmi_attach(ar);
	if (status) {
		ath10k_err("WMI attach failed: %d\n", status);
		goto err;
	}

	status = ath10k_htc_wait_target(&ar->htc);
	if (status)
		goto err_wmi_detach;

	status = ath10k_htt_attach(ar);
	if (status) {
		ath10k_err("could not attach htt (%d)\n", status);
		goto err_wmi_detach;
	}

	status = ath10k_init_connect_htc(ar);
	if (status)
		goto err_htt_detach;

	ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version);

	status = ath10k_check_fw_version(ar);
	if (status)
		goto err_disconnect_htc;

	status = ath10k_wmi_cmd_init(ar);
	if (status) {
		ath10k_err("could not send WMI init command (%d)\n", status);
		goto err_disconnect_htc;
	}

	status = ath10k_wmi_wait_for_unified_ready(ar);
	if (status <= 0) {
		ath10k_err("wmi unified ready event not received\n");
		status = -ETIMEDOUT;
		goto err_disconnect_htc;
	}

	status = ath10k_htt_attach_target(&ar->htt);
	if (status)
		goto err_disconnect_htc;

	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;

	return 0;

err_disconnect_htc:
	ath10k_htc_stop(&ar->htc);
err_htt_detach:
	ath10k_htt_detach(&ar->htt);
err_wmi_detach:
	ath10k_wmi_detach(ar);
err:
	return status;
}