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

Commit e19179b0 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "UPSTREAM: ath10k: Fix encoding for protected management frames"

parents 6e0829cb 56ae9bd2
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
@@ -538,6 +539,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
		.hw_ops = &wcn3990_ops,
		.decap_align_bytes = 1,
		.num_peers = TARGET_HL_10_TLV_NUM_PEERS,
		.n_cipher_suites = 11,
		.ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT,
		.num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES,
		.target_64bit = true,
@@ -2100,6 +2102,7 @@ static void ath10k_core_restart(struct work_struct *work)
	complete(&ar->offchan_tx_completed);
	complete(&ar->install_key_done);
	complete(&ar->vdev_setup_done);
	complete(&ar->vdev_delete_done);
	complete(&ar->thermal.wmi_sync);
	complete(&ar->bss_survey_done);
	wake_up(&ar->htt.empty_tx_wq);
@@ -3002,8 +3005,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,

	init_completion(&ar->install_key_done);
	init_completion(&ar->vdev_setup_done);
	init_completion(&ar->vdev_delete_done);
	init_completion(&ar->thermal.wmi_sync);
	init_completion(&ar->bss_survey_done);
	init_completion(&ar->peer_delete_done);

	INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);

+7 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
@@ -375,6 +376,7 @@ struct ath10k_sta {
};

#define ATH10K_VDEV_SETUP_TIMEOUT_HZ	(5 * HZ)
#define ATH10K_VDEV_DELETE_TIMEOUT_HZ	(5 * HZ)

enum ath10k_beacon_state {
	ATH10K_BEACON_SCHEDULED = 0,
@@ -913,6 +915,7 @@ struct ath10k {

	int last_wmi_vdev_start_status;
	struct completion vdev_setup_done;
	struct completion vdev_delete_done;

	struct workqueue_struct *workqueue;
	/* Auxiliary workqueue */
@@ -1037,8 +1040,11 @@ struct ath10k {

	u32 ampdu_reference;

	const u8 *wmi_key_cipher;
	void *ce_priv;

	struct completion peer_delete_done;

	/* must be last */
	u8 drv_priv[0] __aligned(sizeof(void *));
};
+60 −8
Original line number Diff line number Diff line
@@ -231,24 +231,24 @@ static int ath10k_send_key(struct ath10k_vif *arvif,

	switch (key->cipher) {
	case WLAN_CIPHER_SUITE_CCMP:
		arg.key_cipher = WMI_CIPHER_AES_CCM;
		arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM];
		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
		break;
	case WLAN_CIPHER_SUITE_TKIP:
		arg.key_cipher = WMI_CIPHER_TKIP;
		arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_TKIP];
		arg.key_txmic_len = 8;
		arg.key_rxmic_len = 8;
		break;
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
		arg.key_cipher = WMI_CIPHER_WEP;
		arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_WEP];
		break;
	case WLAN_CIPHER_SUITE_CCMP_256:
		arg.key_cipher = WMI_CIPHER_AES_CCM;
		arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM];
		break;
	case WLAN_CIPHER_SUITE_GCMP:
	case WLAN_CIPHER_SUITE_GCMP_256:
		arg.key_cipher = WMI_CIPHER_AES_GCM;
		arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_GCM];
		break;
	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
@@ -265,7 +265,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;

	if (cmd == DISABLE_KEY) {
		arg.key_cipher = WMI_CIPHER_NONE;
		arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_NONE];
		arg.key_data = NULL;
	}

@@ -685,6 +685,26 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
	*def = &conf->def;
}

static void ath10k_wait_for_peer_delete_done(struct ath10k *ar, u32 vdev_id,
					     const u8 *addr)
{
	unsigned long time_left;
	int ret;

	if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
		ret = ath10k_wait_for_peer_deleted(ar, vdev_id, addr);
		if (ret) {
			ath10k_warn(ar, "failed wait for peer deleted");
			return;
		}

		time_left = wait_for_completion_timeout(&ar->peer_delete_done,
							5 * HZ);
		if (!time_left)
			ath10k_warn(ar, "Timeout in receiving peer delete response\n");
	}
}

static int ath10k_peer_create(struct ath10k *ar,
			      struct ieee80211_vif *vif,
			      struct ieee80211_sta *sta,
@@ -729,7 +749,7 @@ static int ath10k_peer_create(struct ath10k *ar,
		spin_unlock_bh(&ar->data_lock);
		ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n",
			    addr, vdev_id);
		ath10k_wmi_peer_delete(ar, vdev_id, addr);
		ath10k_wait_for_peer_delete_done(ar, vdev_id, addr);
		return -ENOENT;
	}

@@ -811,6 +831,18 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
	if (ret)
		return ret;

	if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
		unsigned long time_left;

		time_left = wait_for_completion_timeout
			    (&ar->peer_delete_done, 5 * HZ);

		if (!time_left) {
			ath10k_warn(ar, "Timeout in receiving peer delete response\n");
			return -ETIMEDOUT;
		}
	}

	ar->num_peers--;

	return 0;
@@ -1003,6 +1035,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
	arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;

	reinit_completion(&ar->vdev_setup_done);
	reinit_completion(&ar->vdev_delete_done);

	ret = ath10k_wmi_vdev_start(ar, &arg);
	if (ret) {
@@ -1052,6 +1085,7 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar)
			    ar->monitor_vdev_id, ret);

	reinit_completion(&ar->vdev_setup_done);
	reinit_completion(&ar->vdev_delete_done);

	ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
	if (ret)
@@ -1393,6 +1427,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
	lockdep_assert_held(&ar->conf_mutex);

	reinit_completion(&ar->vdev_setup_done);
	reinit_completion(&ar->vdev_delete_done);

	ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id);
	if (ret) {
@@ -1429,6 +1464,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
	lockdep_assert_held(&ar->conf_mutex);

	reinit_completion(&ar->vdev_setup_done);
	reinit_completion(&ar->vdev_delete_done);

	arg.vdev_id = arvif->vdev_id;
	arg.dtim_period = arvif->dtim_period;
@@ -5244,8 +5280,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,

err_peer_delete:
	if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
	    arvif->vdev_type == WMI_VDEV_TYPE_IBSS)
	    arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
		ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr);
		ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id,
						 vif->addr);
	}

err_vdev_delete:
	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
@@ -5280,6 +5319,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
	struct ath10k *ar = hw->priv;
	struct ath10k_vif *arvif = (void *)vif->drv_priv;
	struct ath10k_peer *peer;
	unsigned long time_left;
	int ret;
	int i;

@@ -5310,6 +5350,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
			ath10k_warn(ar, "failed to submit AP/IBSS self-peer removal on vdev %i: %d\n",
				    arvif->vdev_id, ret);

		ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id,
						 vif->addr);
		kfree(arvif->u.ap.noa_data);
	}

@@ -5321,6 +5363,15 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
		ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n",
			    arvif->vdev_id, ret);

	if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
		time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
							ATH10K_VDEV_DELETE_TIMEOUT_HZ);
		if (time_left == 0) {
			ath10k_warn(ar, "Timeout in receiving vdev delete response\n");
			goto out;
		}
	}

	/* Some firmware revisions don't notify host about self-peer removal
	 * until after associated vdev is deleted.
	 */
@@ -5371,6 +5422,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,

	ath10k_mac_txq_unref(ar, vif->txq);

out:
	mutex_unlock(&ar->conf_mutex);
}

+60 −4
Original line number Diff line number Diff line
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
@@ -222,6 +223,13 @@ static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
	return 0;
}

static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar,
						  struct sk_buff *skb)
{
	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n");
	complete(&ar->vdev_delete_done);
}

static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
					  struct sk_buff *skb)
{
@@ -412,6 +420,24 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
	return 0;
}

static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
						 struct sk_buff *skb)
{
	struct wmi_peer_delete_resp_ev_arg *arg;
	struct wmi_tlv *tlv_hdr;

	tlv_hdr = (struct wmi_tlv *)skb->data;
	arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;

	ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
	ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");

	complete(&ar->peer_delete_done);

	return 0;
}

/***********/
/* TLV ops */
/***********/
@@ -468,6 +494,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
	case WMI_TLV_VDEV_STOPPED_EVENTID:
		ath10k_wmi_event_vdev_stopped(ar, skb);
		break;
	case WMI_TLV_VDEV_DELETE_RESP_EVENTID:
		ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb);
		break;
	case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
		ath10k_wmi_event_peer_sta_kickout(ar, skb);
		break;
@@ -555,6 +584,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
	case WMI_TLV_TX_PAUSE_EVENTID:
		ath10k_wmi_tlv_event_tx_pause(ar, skb);
		break;
	case WMI_TLV_PEER_DELETE_RESP_EVENTID:
		ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
		break;
	default:
		ath10k_warn(ar, "Unknown eventid: %d\n", id);
		break;
@@ -1704,6 +1736,28 @@ ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
	return skb;
}

static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar,
					      enum wmi_vdev_subtype subtype)
{
	switch (subtype) {
	case WMI_VDEV_SUBTYPE_NONE:
		return WMI_TLV_VDEV_SUBTYPE_NONE;
	case WMI_VDEV_SUBTYPE_P2P_DEVICE:
		return WMI_TLV_VDEV_SUBTYPE_P2P_DEV;
	case WMI_VDEV_SUBTYPE_P2P_CLIENT:
		return WMI_TLV_VDEV_SUBTYPE_P2P_CLI;
	case WMI_VDEV_SUBTYPE_P2P_GO:
		return WMI_TLV_VDEV_SUBTYPE_P2P_GO;
	case WMI_VDEV_SUBTYPE_PROXY_STA:
		return WMI_TLV_VDEV_SUBTYPE_PROXY_STA;
	case WMI_VDEV_SUBTYPE_MESH_11S:
		return WMI_TLV_VDEV_SUBTYPE_MESH_11S;
	case WMI_VDEV_SUBTYPE_MESH_NON_11S:
		return -ENOTSUPP;
	}
	return -ENOTSUPP;
}

static struct sk_buff *
ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
				  u32 vdev_id,
@@ -1932,9 +1986,11 @@ ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
	size_t len;
	void *ptr;

	if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL)
	if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
	    arg->key_data)
		return ERR_PTR(-EINVAL);
	if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL)
	if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
	    !arg->key_data)
		return ERR_PTR(-EINVAL);

	len = sizeof(*tlv) + sizeof(*cmd) +
@@ -2611,7 +2667,7 @@ ath10k_wmi_tlv_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
	     ieee80211_is_deauth(hdr->frame_control) ||
	     ieee80211_is_disassoc(hdr->frame_control)) &&
	     ieee80211_has_protected(hdr->frame_control)) {
		len += IEEE80211_CCMP_MIC_LEN;
		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
		buf_len += IEEE80211_CCMP_MIC_LEN;
	}

@@ -3826,7 +3882,7 @@ static const struct wmi_ops wmi_tlv_ops = {
	.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
	.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
	.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
	.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
	.get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype,
	.gen_echo = ath10k_wmi_tlv_op_gen_echo,
	.gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
	.gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
@@ -309,11 +310,15 @@ enum wmi_tlv_event_id {
	WMI_TLV_VDEV_STOPPED_EVENTID,
	WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID,
	WMI_TLV_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID,
	WMI_TLV_VDEV_TSF_REPORT_EVENTID,
	WMI_TLV_VDEV_DELETE_RESP_EVENTID,
	WMI_TLV_PEER_STA_KICKOUT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_PEER),
	WMI_TLV_PEER_INFO_EVENTID,
	WMI_TLV_PEER_TX_FAIL_CNT_THR_EVENTID,
	WMI_TLV_PEER_ESTIMATED_LINKSPEED_EVENTID,
	WMI_TLV_PEER_STATE_EVENTID,
	WMI_TLV_PEER_ASSOC_CONF_EVENTID,
	WMI_TLV_PEER_DELETE_RESP_EVENTID,
	WMI_TLV_MGMT_RX_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MGMT),
	WMI_TLV_HOST_SWBA_EVENTID,
	WMI_TLV_TBTTOFFSET_UPDATE_EVENTID,
@@ -1554,6 +1559,10 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
	       WMI_SERVICE_SAP_AUTH_OFFLOAD, len);
	SVCMAP(WMI_TLV_SERVICE_MGMT_TX_WMI,
	       WMI_SERVICE_MGMT_TX_WMI, len);
	SVCMAP(WMI_TLV_SERVICE_MESH_11S,
	       WMI_SERVICE_MESH_11S, len);
	SVCMAP(WMI_TLV_SERVICE_SYNC_DELETE_CMDS,
	       WMI_SERVICE_SYNC_DELETE_CMDS, len);
}

static inline void
@@ -1721,6 +1730,16 @@ struct wmi_tlv_start_scan_cmd {
	struct wmi_mac_addr mac_mask;
} __packed;

enum wmi_tlv_vdev_subtype {
	WMI_TLV_VDEV_SUBTYPE_NONE	= 0,
	WMI_TLV_VDEV_SUBTYPE_P2P_DEV	= 1,
	WMI_TLV_VDEV_SUBTYPE_P2P_CLI	= 2,
	WMI_TLV_VDEV_SUBTYPE_P2P_GO	= 3,
	WMI_TLV_VDEV_SUBTYPE_PROXY_STA	= 4,
	WMI_TLV_VDEV_SUBTYPE_MESH	= 5,
	WMI_TLV_VDEV_SUBTYPE_MESH_11S	= 6,
};

struct wmi_tlv_vdev_start_cmd {
	__le32 vdev_id;
	__le32 requestor_id;
Loading