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

Commit 946951e1 authored by John W. Linville's avatar John W. Linville
Browse files

Merge branch 'for-linville' of git://github.com/kvalo/ath

parents d1e2586f 9d0e2f07
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -637,6 +637,7 @@ static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state,
		ath10k_pci_wake(ar);
		src_ring->hw_index =
			ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
		src_ring->hw_index &= nentries_mask;
		ath10k_pci_sleep(ar);
	}
	read_index = src_ring->hw_index;
@@ -950,10 +951,12 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,

	ath10k_pci_wake(ar);
	src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
	src_ring->sw_index &= src_ring->nentries_mask;
	src_ring->hw_index = src_ring->sw_index;

	src_ring->write_index =
		ath10k_ce_src_ring_write_index_get(ar, ctrl_addr);
	src_ring->write_index &= src_ring->nentries_mask;
	ath10k_pci_sleep(ar);

	src_ring->per_transfer_context = (void **)ptr;
@@ -1035,8 +1038,10 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,

	ath10k_pci_wake(ar);
	dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
	dest_ring->sw_index &= dest_ring->nentries_mask;
	dest_ring->write_index =
		ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr);
	dest_ring->write_index &= dest_ring->nentries_mask;
	ath10k_pci_sleep(ar);

	dest_ring->per_transfer_context = (void **)ptr;
+8 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#define ATH10K_SCAN_ID 0
#define WMI_READY_TIMEOUT (5 * HZ)
#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
#define ATH10K_NUM_CHANS 38

/* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95
@@ -285,6 +286,7 @@ struct ath10k {
	u32 hw_max_tx_power;
	u32 ht_cap_info;
	u32 vht_cap_info;
	u32 num_rf_chains;

	struct targetdef *targetdef;
	struct hostdef *hostdef;
@@ -374,6 +376,12 @@ struct ath10k {

	struct work_struct restart_work;

	/* cycle count is reported twice for each visited channel during scan.
	 * access protected by data_lock */
	u32 survey_last_rx_clear_count;
	u32 survey_last_cycle_count;
	struct survey_info survey[ATH10K_NUM_CHANS];

#ifdef CONFIG_ATH10K_DEBUGFS
	struct ath10k_debug debug;
#endif
+40 −0
Original line number Diff line number Diff line
@@ -804,6 +804,37 @@ static bool ath10k_htt_rx_has_fcs_err(struct sk_buff *skb)
	return false;
}

static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
{
	struct htt_rx_desc *rxd;
	u32 flags, info;
	bool is_ip4, is_ip6;
	bool is_tcp, is_udp;
	bool ip_csum_ok, tcpudp_csum_ok;

	rxd = (void *)skb->data - sizeof(*rxd);
	flags = __le32_to_cpu(rxd->attention.flags);
	info = __le32_to_cpu(rxd->msdu_start.info1);

	is_ip4 = !!(info & RX_MSDU_START_INFO1_IPV4_PROTO);
	is_ip6 = !!(info & RX_MSDU_START_INFO1_IPV6_PROTO);
	is_tcp = !!(info & RX_MSDU_START_INFO1_TCP_PROTO);
	is_udp = !!(info & RX_MSDU_START_INFO1_UDP_PROTO);
	ip_csum_ok = !(flags & RX_ATTENTION_FLAGS_IP_CHKSUM_FAIL);
	tcpudp_csum_ok = !(flags & RX_ATTENTION_FLAGS_TCP_UDP_CHKSUM_FAIL);

	if (!is_ip4 && !is_ip6)
		return CHECKSUM_NONE;
	if (!is_tcp && !is_udp)
		return CHECKSUM_NONE;
	if (!ip_csum_ok)
		return CHECKSUM_NONE;
	if (!tcpudp_csum_ok)
		return CHECKSUM_NONE;

	return CHECKSUM_UNNECESSARY;
}

static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
				  struct htt_rx_indication *rx)
{
@@ -815,6 +846,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
	u8 *fw_desc;
	int i, j;
	int ret;
	int ip_summed;

	memset(&info, 0, sizeof(info));

@@ -889,6 +921,11 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
				continue;
			}

			/* The skb is not yet processed and it may be
			 * reallocated. Since the offload is in the original
			 * skb extract the checksum now and assign it later */
			ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);

			info.skb     = msdu_head;
			info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head);
			info.signal  = ATH10K_DEFAULT_NOISE_FLOOR;
@@ -914,6 +951,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
			if (ath10k_htt_rx_hdr_is_amsdu((void *)info.skb->data))
				ath10k_dbg(ATH10K_DBG_HTT, "htt mpdu is amsdu\n");

			info.skb->ip_summed = ip_summed;

			ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt mpdu: ",
					info.skb->data, info.skb->len);
			ath10k_process_rx(htt->ar, &info);
@@ -980,6 +1019,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
	info.status = HTT_RX_IND_MPDU_STATUS_OK;
	info.encrypt_type = MS(__le32_to_cpu(rxd->mpdu_start.info0),
				RX_MPDU_START_INFO0_ENCRYPT_TYPE);
	info.skb->ip_summed = ath10k_htt_rx_get_csum_state(info.skb);

	if (tkip_mic_err) {
		ath10k_warn("tkip mic error\n");
+2 −0
Original line number Diff line number Diff line
@@ -465,6 +465,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
	flags1  = 0;
	flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
	flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;

	frags_paddr = ATH10K_SKB_CB(txfrag)->paddr;

+63 −16
Original line number Diff line number Diff line
@@ -1406,9 +1406,9 @@ static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
		return;

	qos_ctl = ieee80211_get_qos_ctl(hdr);
	memmove(qos_ctl, qos_ctl + IEEE80211_QOS_CTL_LEN,
		skb->len - ieee80211_hdrlen(hdr->frame_control));
	skb_trim(skb, skb->len - IEEE80211_QOS_CTL_LEN);
	memmove(skb->data + IEEE80211_QOS_CTL_LEN,
		skb->data, (void *)qos_ctl - (void *)skb->data);
	skb_pull(skb, IEEE80211_QOS_CTL_LEN);
}

static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
@@ -1925,6 +1925,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,

	mutex_lock(&ar->conf_mutex);

	memset(arvif, 0, sizeof(*arvif));

	arvif->ar = ar;
	arvif->vif = vif;

@@ -2338,6 +2340,8 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
			arg.ssids[i].len  = req->ssids[i].ssid_len;
			arg.ssids[i].ssid = req->ssids[i].ssid;
		}
	} else {
		arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
	}

	if (req->n_channels) {
@@ -2934,6 +2938,41 @@ static void ath10k_restart_complete(struct ieee80211_hw *hw)
	mutex_unlock(&ar->conf_mutex);
}

static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
			     struct survey_info *survey)
{
	struct ath10k *ar = hw->priv;
	struct ieee80211_supported_band *sband;
	struct survey_info *ar_survey = &ar->survey[idx];
	int ret = 0;

	mutex_lock(&ar->conf_mutex);

	sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
	if (sband && idx >= sband->n_channels) {
		idx -= sband->n_channels;
		sband = NULL;
	}

	if (!sband)
		sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];

	if (!sband || idx >= sband->n_channels) {
		ret = -ENOENT;
		goto exit;
	}

	spin_lock_bh(&ar->data_lock);
	memcpy(survey, ar_survey, sizeof(*survey));
	spin_unlock_bh(&ar->data_lock);

	survey->channel = &sband->channels[idx];

exit:
	mutex_unlock(&ar->conf_mutex);
	return ret;
}

static const struct ieee80211_ops ath10k_ops = {
	.tx				= ath10k_tx,
	.start				= ath10k_start,
@@ -2955,6 +2994,7 @@ static const struct ieee80211_ops ath10k_ops = {
	.flush				= ath10k_flush,
	.tx_last_beacon			= ath10k_tx_last_beacon,
	.restart_complete		= ath10k_restart_complete,
	.get_survey			= ath10k_get_survey,
#ifdef CONFIG_PM
	.suspend			= ath10k_suspend,
	.resume				= ath10k_resume,
@@ -3076,9 +3116,15 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
	.max	= 8,
	.types	= BIT(NL80211_IFTYPE_STATION)
		| BIT(NL80211_IFTYPE_P2P_CLIENT)
		| BIT(NL80211_IFTYPE_P2P_GO)
		| BIT(NL80211_IFTYPE_AP)
	}
	},
	{
	.max	= 3,
	.types	= BIT(NL80211_IFTYPE_P2P_GO)
	},
	{
	.max	= 7,
	.types	= BIT(NL80211_IFTYPE_AP)
	},
};

static const struct ieee80211_iface_combination ath10k_if_comb = {
@@ -3093,19 +3139,18 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
{
	struct ieee80211_sta_vht_cap vht_cap = {0};
	u16 mcs_map;
	int i;

	vht_cap.vht_supported = 1;
	vht_cap.cap = ar->vht_cap_info;

	/* FIXME: check dynamically how many streams board supports */
	mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
		IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
		IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 |
		IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
		IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
		IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
		IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
		IEEE80211_VHT_MCS_NOT_SUPPORTED << 14;
	mcs_map = 0;
	for (i = 0; i < 8; i++) {
		if (i < ar->num_rf_chains)
			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
		else
			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
	}

	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
@@ -3168,7 +3213,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;

	for (i = 0; i < WMI_MAX_SPATIAL_STREAM; i++)
	for (i = 0; i < ar->num_rf_chains; i++)
		ht_cap.mcs.rx_mask[i] = 0xFF;

	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
@@ -3310,6 +3355,8 @@ int ath10k_mac_register(struct ath10k *ar)
	ar->hw->wiphy->iface_combinations = &ath10k_if_comb;
	ar->hw->wiphy->n_iface_combinations = 1;

	ar->hw->netdev_features = NETIF_F_HW_CSUM;

	ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
			    ath10k_reg_notifier);
	if (ret) {
Loading