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

Commit 73b25f66 authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge ath-next from ath.git

Major changes in ath10k:

* enable channel 144 on 5 GHz
* enable Adaptive Noise Immunity (ANI) by default
* add Wake on Wireless LAN (WOW) patterns support
* add basic Tunneled Direct Link Setup (TDLS) support
* add multi-channel support for QCA6174
* enable IBSS RSN support
* enable Bluetooth Coexistance whenever firmware supports it
* add more versatile way to set bitrates used by the firmware
parents 2decb268 45c9abc0
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -10,13 +10,15 @@ ath10k_core-y += mac.o \
		 wmi.o \
		 wmi-tlv.o \
		 bmi.o \
		 hw.o
		 hw.o \
		 p2p.o

ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
ath10k_core-$(CONFIG_THERMAL) += thermal.o
ath10k_core-$(CONFIG_MAC80211_DEBUGFS) += debugfs_sta.o
ath10k_core-$(CONFIG_PM) += wow.o

obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
ath10k_pci-y += pci.o \
+121 −40
Original line number Diff line number Diff line
@@ -482,31 +482,79 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
	return 0;
}

static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
static int ath10k_core_fetch_spec_board_file(struct ath10k *ar)
{
	int ret = 0;
	char filename[100];

	if (ar->hw_params.fw.fw == NULL) {
		ath10k_err(ar, "firmware file not defined\n");
		return -EINVAL;
	scnprintf(filename, sizeof(filename), "board-%s-%s.bin",
		  ath10k_bus_str(ar->hif.bus), ar->spec_board_id);

	ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
	if (IS_ERR(ar->board))
		return PTR_ERR(ar->board);

	ar->board_data = ar->board->data;
	ar->board_len = ar->board->size;
	ar->spec_board_loaded = true;

	return 0;
}

	if (ar->hw_params.fw.board == NULL) {
		ath10k_err(ar, "board data file not defined");
static int ath10k_core_fetch_generic_board_file(struct ath10k *ar)
{
	if (!ar->hw_params.fw.board) {
		ath10k_err(ar, "failed to find board file fw entry\n");
		return -EINVAL;
	}

	ar->board = ath10k_fetch_fw_file(ar,
					 ar->hw_params.fw.dir,
					 ar->hw_params.fw.board);
	if (IS_ERR(ar->board)) {
		ret = PTR_ERR(ar->board);
		ath10k_err(ar, "could not fetch board data (%d)\n", ret);
		goto err;
	}
	if (IS_ERR(ar->board))
		return PTR_ERR(ar->board);

	ar->board_data = ar->board->data;
	ar->board_len = ar->board->size;
	ar->spec_board_loaded = false;

	return 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;
}

static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
{
	int ret = 0;

	if (ar->hw_params.fw.fw == NULL) {
		ath10k_err(ar, "firmware file not defined\n");
		return -EINVAL;
	}

	ar->firmware = ath10k_fetch_fw_file(ar,
					    ar->hw_params.fw.dir,
@@ -675,6 +723,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",
				   ar->wmi.op_version);
			break;
		case ATH10K_FW_IE_HTT_OP_VERSION:
			if (ie_len != sizeof(u32))
				break;

			version = (__le32 *)data;

			ar->htt.op_version = le32_to_cpup(version);

			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n",
				   ar->htt.op_version);
			break;
		default:
			ath10k_warn(ar, "Unknown FW IE: %u\n",
				    le32_to_cpu(hdr->id));
@@ -695,27 +754,6 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
		goto err;
	}

	/* now fetch the board file */
	if (ar->hw_params.fw.board == NULL) {
		ath10k_err(ar, "board data file not defined");
		ret = -EINVAL;
		goto err;
	}

	ar->board = ath10k_fetch_fw_file(ar,
					 ar->hw_params.fw.dir,
					 ar->hw_params.fw.board);
	if (IS_ERR(ar->board)) {
		ret = PTR_ERR(ar->board);
		ath10k_err(ar, "could not fetch board data '%s/%s' (%d)\n",
			   ar->hw_params.fw.dir, ar->hw_params.fw.board,
			   ret);
		goto err;
	}

	ar->board_data = ar->board->data;
	ar->board_len = ar->board->size;

	return 0;

err:
@@ -730,6 +768,19 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
	/* calibration file is optional, don't check for any errors */
	ath10k_fetch_cal_file(ar);

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

	ar->fw_api = 5;
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);

	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE);
	if (ret == 0)
		goto success;

	ar->fw_api = 4;
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);

@@ -958,6 +1009,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
		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;
		break;
	case ATH10K_FW_WMI_OP_VERSION_10_1:
	case ATH10K_FW_WMI_OP_VERSION_10_2:
@@ -966,12 +1019,17 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
		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;
		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;
		break;
	case ATH10K_FW_WMI_OP_VERSION_UNSET:
	case ATH10K_FW_WMI_OP_VERSION_MAX:
@@ -979,6 +1037,29 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
		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_UNSET:
		case ATH10K_FW_WMI_OP_VERSION_MAX:
			WARN_ON(1);
			return -EINVAL;
		}
	}

	return 0;
}

@@ -1080,9 +1161,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)

	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
		status = ath10k_wmi_wait_for_service_ready(ar);
		if (status <= 0) {
		if (status) {
			ath10k_warn(ar, "wmi service ready event not received");
			status = -ETIMEDOUT;
			goto err_hif_stop;
		}
	}
@@ -1098,9 +1178,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
	}

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

@@ -1151,6 +1230,7 @@ EXPORT_SYMBOL(ath10k_core_start);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)
{
	int ret;
	unsigned long time_left;

	reinit_completion(&ar->target_suspend);

@@ -1160,9 +1240,9 @@ int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)
		return ret;
	}

	ret = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);
	time_left = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);

	if (ret == 0) {
	if (!time_left) {
		ath10k_warn(ar, "suspend timed out - target pause event never came\n");
		return -ETIMEDOUT;
	}
@@ -1386,6 +1466,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
	init_completion(&ar->scan.completed);
	init_completion(&ar->scan.on_channel);
	init_completion(&ar->target_suspend);
	init_completion(&ar->wow.wakeup_completed);

	init_completion(&ar->install_key_done);
	init_completion(&ar->vdev_setup_done);
+42 −6
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "../dfs_pattern_detector.h"
#include "spectral.h"
#include "thermal.h"
#include "wow.h"

#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -43,15 +44,16 @@
#define ATH10K_SCAN_ID 0
#define WMI_READY_TIMEOUT (5 * HZ)
#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
#define ATH10K_NUM_CHANS 38
#define ATH10K_CONNECTION_LOSS_HZ (3*HZ)
#define ATH10K_NUM_CHANS 39

/* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95

#define ATH10K_MAX_NUM_MGMT_PENDING 128

/* number of failed packets */
#define ATH10K_KICKOUT_THRESHOLD 50
/* number of failed packets (20 packets with 16 sw reties each) */
#define ATH10K_KICKOUT_THRESHOLD (20 * 16)

/*
 * Use insanely high numbers to make sure that the firmware implementation
@@ -82,6 +84,8 @@ struct ath10k_skb_cb {
	dma_addr_t paddr;
	u8 eid;
	u8 vdev_id;
	enum ath10k_hw_txrx_mode txmode;
	bool is_protected;

	struct {
		u8 tid;
@@ -280,6 +284,15 @@ struct ath10k_sta {
#endif
};

struct ath10k_chanctx {
	/* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally
	 * mac80211 should allow some sort of explicit locking to guarantee
	 * that the publicly available chanctx_conf can be accessed safely at
	 * all times.
	 */
	struct ieee80211_chanctx_conf conf;
};

#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)

enum ath10k_beacon_state {
@@ -301,6 +314,7 @@ struct ath10k_vif {
	enum ath10k_beacon_state beacon_state;
	void *beacon_buf;
	dma_addr_t beacon_paddr;
	unsigned long tx_paused; /* arbitrary values defined by target */

	struct ath10k *ar;
	struct ieee80211_vif *vif;
@@ -334,13 +348,13 @@ struct ath10k_vif {
		} ap;
	} u;

	u8 fixed_rate;
	u8 fixed_nss;
	u8 force_sgi;
	bool use_cts_prot;
	int num_legacy_stations;
	int txpower;
	struct wmi_wmm_params_all_arg wmm_params;
	struct work_struct ap_csa_work;
	struct delayed_work connection_loss_work;
	struct cfg80211_bitrate_mask bitrate_mask;
};

struct ath10k_vif_iter {
@@ -440,6 +454,12 @@ enum ath10k_fw_features {
	 */
	ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT = 5,

	/* Some firmware revisions have an incomplete WoWLAN implementation
	 * despite WMI service bit being advertised. This feature flag is used
	 * to distinguish whether WoWLAN is really supported or not.
	 */
	ATH10K_FW_FEATURE_WOWLAN_SUPPORT = 6,

	/* keep last */
	ATH10K_FW_FEATURE_COUNT,
};
@@ -498,6 +518,11 @@ static inline const char *ath10k_scan_state_str(enum ath10k_scan_state state)
	return "unknown";
}

enum ath10k_tx_pause_reason {
	ATH10K_TX_PAUSE_Q_FULL,
	ATH10K_TX_PAUSE_MAX,
};

struct ath10k {
	struct ath_common ath_common;
	struct ieee80211_hw *hw;
@@ -511,12 +536,15 @@ struct ath10k {
	u32 fw_version_minor;
	u16 fw_version_release;
	u16 fw_version_build;
	u32 fw_stats_req_mask;
	u32 phy_capability;
	u32 hw_min_tx_power;
	u32 hw_max_tx_power;
	u32 ht_cap_info;
	u32 vht_cap_info;
	u32 num_rf_chains;
	/* protected by conf_mutex */
	bool ani_enabled;

	DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);

@@ -565,6 +593,9 @@ struct ath10k {

	const struct firmware *cal_file;

	char spec_board_id[100];
	bool spec_board_loaded;

	int fw_api;
	enum ath10k_cal_mode cal_mode;

@@ -593,6 +624,7 @@ struct ath10k {
	struct cfg80211_chan_def chandef;

	unsigned long long free_vdev_map;
	struct ath10k_vif *monitor_arvif;
	bool monitor;
	int monitor_vdev_id;
	bool monitor_started;
@@ -633,6 +665,7 @@ struct ath10k {
	int max_num_peers;
	int max_num_stations;
	int max_num_vdevs;
	int max_num_tdls_vdevs;

	struct work_struct offchan_tx_work;
	struct sk_buff_head offchan_tx_queue;
@@ -655,6 +688,8 @@ struct ath10k {

	struct dfs_pattern_detector *dfs_detector;

	unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */

#ifdef CONFIG_ATH10K_DEBUGFS
	struct ath10k_debug debug;
#endif
@@ -686,6 +721,7 @@ struct ath10k {
	} stats;

	struct ath10k_thermal thermal;
	struct ath10k_wow wow;

	/* must be last */
	u8 drv_priv[0] __aligned(sizeof(void *));
+117 −10
Original line number Diff line number Diff line
@@ -124,10 +124,14 @@ EXPORT_SYMBOL(ath10k_info);

void ath10k_print_driver_info(struct ath10k *ar)
{
	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
	ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
		    ar->hw_params.name,
		    ar->target_version,
		    ar->chip_id,
		    (strlen(ar->spec_board_id) > 0 ? ", " : ""),
		    ar->spec_board_id,
		    (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded
		     ? " fallback" : ""),
		    ar->hw->wiphy->fw_version,
		    ar->fw_api,
		    ar->htt.target_version_major,
@@ -380,7 +384,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)

static int ath10k_debug_fw_stats_request(struct ath10k *ar)
{
	unsigned long timeout;
	unsigned long timeout, time_left;
	int ret;

	lockdep_assert_held(&ar->conf_mutex);
@@ -395,18 +399,16 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)

		reinit_completion(&ar->debug.fw_stats_complete);

		ret = ath10k_wmi_request_stats(ar,
					       WMI_STAT_PDEV |
					       WMI_STAT_VDEV |
					       WMI_STAT_PEER);
		ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
		if (ret) {
			ath10k_warn(ar, "could not request stats (%d)\n", ret);
			return ret;
		}

		ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
		time_left =
		wait_for_completion_timeout(&ar->debug.fw_stats_complete,
					    1 * HZ);
		if (ret == 0)
		if (!time_left)
			return -ETIMEDOUT;

		spin_lock_bh(&ar->data_lock);
@@ -1708,6 +1710,61 @@ static int ath10k_debug_cal_data_release(struct inode *inode,
	return 0;
}

static ssize_t ath10k_write_ani_enable(struct file *file,
				       const char __user *user_buf,
				       size_t count, loff_t *ppos)
{
	struct ath10k *ar = file->private_data;
	int ret;
	u8 enable;

	if (kstrtou8_from_user(user_buf, count, 0, &enable))
		return -EINVAL;

	mutex_lock(&ar->conf_mutex);

	if (ar->ani_enabled == enable) {
		ret = count;
		goto exit;
	}

	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
					enable);
	if (ret) {
		ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
		goto exit;
	}
	ar->ani_enabled = enable;

	ret = count;

exit:
	mutex_unlock(&ar->conf_mutex);

	return ret;
}

static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
				      size_t count, loff_t *ppos)
{
	struct ath10k *ar = file->private_data;
	int len = 0;
	char buf[32];

	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
			ar->ani_enabled);

	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

static const struct file_operations fops_ani_enable = {
	.read = ath10k_read_ani_enable,
	.write = ath10k_write_ani_enable,
	.open = simple_open,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

static const struct file_operations fops_cal_data = {
	.open = ath10k_debug_cal_data_open,
	.read = ath10k_debug_cal_data_read,
@@ -1991,6 +2048,50 @@ static const struct file_operations fops_pktlog_filter = {
	.open = simple_open
};

static ssize_t ath10k_write_quiet_period(struct file *file,
					 const char __user *ubuf,
					 size_t count, loff_t *ppos)
{
	struct ath10k *ar = file->private_data;
	u32 period;

	if (kstrtouint_from_user(ubuf, count, 0, &period))
		return -EINVAL;

	if (period < ATH10K_QUIET_PERIOD_MIN) {
		ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
			    period);
		return -EINVAL;
	}
	mutex_lock(&ar->conf_mutex);
	ar->thermal.quiet_period = period;
	ath10k_thermal_set_throttling(ar);
	mutex_unlock(&ar->conf_mutex);

	return count;
}

static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
					size_t count, loff_t *ppos)
{
	char buf[32];
	struct ath10k *ar = file->private_data;
	int len = 0;

	mutex_lock(&ar->conf_mutex);
	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
			ar->thermal.quiet_period);
	mutex_unlock(&ar->conf_mutex);

	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
}

static const struct file_operations fops_quiet_period = {
	.read = ath10k_read_quiet_period,
	.write = ath10k_write_quiet_period,
	.open = simple_open
};

int ath10k_debug_create(struct ath10k *ar)
{
	ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
@@ -2068,6 +2169,9 @@ int ath10k_debug_register(struct ath10k *ar)
	debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
			    ar, &fops_cal_data);

	debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR,
			    ar->debug.debugfs_phy, ar, &fops_ani_enable);

	debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
			    ar->debug.debugfs_phy, ar, &fops_nf_cal_period);

@@ -2088,6 +2192,9 @@ int ath10k_debug_register(struct ath10k *ar)
	debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
			    ar->debug.debugfs_phy, ar, &fops_pktlog_filter);

	debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR,
			    ar->debug.debugfs_phy, ar, &fops_quiet_period);

	return 0;
}

+20 −30
Original line number Diff line number Diff line
@@ -86,21 +86,6 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
	ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
}

/* assumes tx_lock is held */
static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep)
{
	struct ath10k *ar = ep->htc->ar;

	if (!ep->tx_credit_flow_enabled)
		return false;
	if (ep->tx_credits >= ep->tx_credits_per_max_message)
		return false;

	ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n",
		   ep->eid);
	return true;
}

static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
				      struct sk_buff *skb)
{
@@ -111,13 +96,10 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
	hdr->eid = ep->eid;
	hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
	hdr->flags = 0;
	hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;

	spin_lock_bh(&ep->htc->tx_lock);
	hdr->seq_no = ep->seq_no++;

	if (ath10k_htc_ep_need_credit_update(ep))
		hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;

	spin_unlock_bh(&ep->htc->tx_lock);
}

@@ -414,7 +396,8 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
		struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;

		switch (__le16_to_cpu(msg->hdr.message_id)) {
		default:
		case ATH10K_HTC_MSG_READY_ID:
		case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
			/* handle HTC control message */
			if (completion_done(&htc->ctl_resp)) {
				/*
@@ -438,6 +421,10 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
			break;
		case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
			htc->htc_ops.target_send_suspend_complete(ar);
			break;
		default:
			ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
			break;
		}
		goto out;
	}
@@ -548,6 +535,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
{
	struct ath10k *ar = htc->ar;
	int i, status = 0;
	unsigned long time_left;
	struct ath10k_htc_svc_conn_req conn_req;
	struct ath10k_htc_svc_conn_resp conn_resp;
	struct ath10k_htc_msg *msg;
@@ -555,9 +543,9 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
	u16 credit_count;
	u16 credit_size;

	status = wait_for_completion_timeout(&htc->ctl_resp,
	time_left = wait_for_completion_timeout(&htc->ctl_resp,
						ATH10K_HTC_WAIT_TIMEOUT_HZ);
	if (status == 0) {
	if (!time_left) {
		/* Workaround: In some cases the PCI HIF doesn't
		 * receive interrupt for the control response message
		 * even if the buffer was completed. It is suspected
@@ -569,10 +557,11 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
		for (i = 0; i < CE_COUNT; i++)
			ath10k_hif_send_complete_check(htc->ar, i, 1);

		status = wait_for_completion_timeout(&htc->ctl_resp,
		time_left =
		wait_for_completion_timeout(&htc->ctl_resp,
					    ATH10K_HTC_WAIT_TIMEOUT_HZ);

		if (status == 0)
		if (!time_left)
			status = -ETIMEDOUT;
	}

@@ -646,6 +635,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
	struct sk_buff *skb;
	unsigned int max_msg_size = 0;
	int length, status;
	unsigned long time_left;
	bool disable_credit_flow_ctrl = false;
	u16 message_id, service_id, flags = 0;
	u8 tx_alloc = 0;
@@ -701,10 +691,10 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
	}

	/* wait for response */
	status = wait_for_completion_timeout(&htc->ctl_resp,
	time_left = wait_for_completion_timeout(&htc->ctl_resp,
						ATH10K_HTC_CONN_SVC_TIMEOUT_HZ);
	if (status == 0) {
		ath10k_err(ar, "Service connect timeout: %d\n", status);
	if (!time_left) {
		ath10k_err(ar, "Service connect timeout\n");
		return -ETIMEDOUT;
	}

Loading