Exemple #1
0
static void r92su_rx_add_radiotap(struct r92su *r92su,
				  rx_hdr *rx_hdr,
				  struct sk_buff *skb,
				  unsigned int rtap_len)
{
	unsigned char *pos;
	struct ieee80211_radiotap_header *rthdr;
	unsigned int rx_mcs;
	bool ht;

	rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
	memset(rthdr, 0, sizeof(*rthdr));

	rthdr->it_present =
		cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
			    (1 << IEEE80211_RADIOTAP_CHANNEL) |
			    (1 << IEEE80211_RADIOTAP_ANTENNA) |
			    (1 << IEEE80211_RADIOTAP_RX_FLAGS) |
			    (1 << IEEE80211_RADIOTAP_TSFT));
	rthdr->it_len = cpu_to_le16(rtap_len);

	pos = (unsigned char *)(rthdr + 1);

	/* Note: the order of the entries is important! */

	/* IEEE80211_RADIOTAP_TSFT + TSFT Alignment */
	while ((pos - (u8 *)rthdr) & 7)
		*pos++ = 0;

	put_unaligned_le64(GET_RX_DESC_TSFL(rx_hdr), pos);
	pos += 8;

	/* IEEE80211_RADIOTAP_FLAGS */
	*pos = IEEE80211_RADIOTAP_F_FCS;
	if (GET_RX_DESC_CRC32(rx_hdr))
		*pos |= IEEE80211_RADIOTAP_F_BADFCS;
	if (GET_RX_DESC_SPLCP(rx_hdr))
		*pos |= IEEE80211_RADIOTAP_F_SHORTPRE;
	pos++;

	rx_mcs = GET_RX_DESC_RX_MCS(rx_hdr);

	/* IEEE80211_RADIOTAP_RATE */
	ht = GET_RX_DESC_RX_HT(rx_hdr);
	if (ht) {
		/* Without rate information don't add it. If we have,
		 * MCS information is a separate field in radiotap,
		 * added below. The byte here is needed as padding
		 * for the channel though, so initialise it to 0.
		 */
		*pos = 0;
	} else {
		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
		*pos = r92su->band_2GHZ.bitrates[rx_mcs].bitrate / 5;
	}
	pos++;

	/* IEEE80211_RADIOTAP_CHANNEL */
	put_unaligned_le16(r92su->current_channel->center_freq, pos);
	pos += 2;
	if (ht)
		put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
				   pos);
	else if (rx_mcs > 3)
		put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
				   pos);
	else
		put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
				   pos);
	pos += 2;

	/* IEEE80211_RADIOTAP_ANTENNA */
	*pos++ = 0;

	/* IEEE80211_RADIOTAP_RX_FLAGS */
	/* ensure 2 byte alignment for the 2 byte field as required */
	if ((pos - (u8 *)rthdr) & 1)
		*pos++ = 0;
	put_unaligned_le16(0, pos);
	pos += 2;

	if (ht) {
		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
		*pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
			 IEEE80211_RADIOTAP_MCS_HAVE_BW;
		*pos = 0;
		if (GET_RX_DESC_BW(rx_hdr))
			*pos |= IEEE80211_RADIOTAP_MCS_BW_40;
		pos++;
		*pos++ = rx_mcs;
	}

	if (GET_RX_DESC_PAGGR(rx_hdr)) {
		u16 flags = 0;

		/* ensure 4 byte alignment */
		while ((pos - (u8 *)rthdr) & 3)
			pos++;

		rthdr->it_present |=
			cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);

		if (GET_RX_DESC_FAGGR(rx_hdr))
			r92su->ampdu_reference++;

		put_unaligned_le32(r92su->ampdu_reference, pos);
		pos += 4;

		/* ampdu flags, no flags ? */
		put_unaligned_le16(flags, pos);
		pos += 2;

		*pos++ = 0;	/* no crc delim */
		*pos++ = 0;
	}
}
Exemple #2
0
bool rtl8822be_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *status,
			     struct ieee80211_rx_status *rx_status, u8 *pdesc,
			     struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u8 *p_phystrpt = NULL;
	struct ieee80211_hdr *hdr;

	u32 phystatus = GET_RX_DESC_PHYST(pdesc);

	if (GET_RX_DESC_C2H(pdesc) == 0)
		status->packet_report_type = NORMAL_RX;
	else
		status->packet_report_type = C2H_PACKET;

	status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc);
	status->rx_drvinfo_size =
		(u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * RX_DRV_INFO_SIZE_UNIT;
	status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03);
	status->icv = (u16)GET_RX_DESC_ICV_ERR(pdesc);
	status->crc = (u16)GET_RX_DESC_CRC32(pdesc);
	status->hwerror = (status->crc | status->icv);
	status->decrypted = !GET_RX_DESC_SWDEC(pdesc);
	status->rate = (u8)GET_RX_DESC_RX_RATE(pdesc);
	status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1);
	status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1);
	status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
	status->is_ht = rtl8822be_get_rxdesc_is_ht(hw, pdesc);
	status->is_vht = rtl8822be_get_rxdesc_is_vht(hw, pdesc);
	status->vht_nss = rtl8822be_get_rx_vht_nss(hw, pdesc);
	status->is_cck = RX_HAL_IS_CCK_RATE(status->rate);

	status->macid = GET_RX_DESC_MACID(pdesc);
	if (GET_RX_DESC_PATTERN_MATCH(pdesc))
		status->wake_match = BIT(2);
	else if (GET_RX_DESC_MAGIC_WAKE(pdesc))
		status->wake_match = BIT(1);
	else if (GET_RX_DESC_UNICAST_WAKE(pdesc))
		status->wake_match = BIT(0);
	else
		status->wake_match = 0;
	if (status->wake_match)
		RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD,
			 "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n",
			 status->wake_match);
	rx_status->freq = hw->conf.chandef.chan->center_freq;
	rx_status->band = hw->conf.chandef.chan->band;

	if (phystatus)
		p_phystrpt = (skb->data + status->rx_bufshift + 24);

	hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size +
				       status->rx_bufshift + 24);

	if (status->crc)
		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;

	if (status->is_ht)
		rx_status->encoding = RX_ENC_HT;
	if (status->is_vht)
		rx_status->encoding = RX_ENC_VHT;

	rx_status->nss = status->vht_nss;

	rx_status->flag |= RX_FLAG_MACTIME_START;

	/* hw will set status->decrypted true, if it finds the
	 * frame is open data frame or mgmt frame.
	 */
	/* So hw will not decryption robust management frame
	 * for IEEE80211w but still set status->decrypted
	 * true, so here we should set it back to undecrypted
	 * for IEEE80211w frame, and mac80211 sw will help
	 * to decrypt it
	 */
	if (status->decrypted) {
		if ((!_ieee80211_is_robust_mgmt_frame(hdr)) &&
		    (ieee80211_has_protected(hdr->frame_control)))
			rx_status->flag |= RX_FLAG_DECRYPTED;
		else
			rx_status->flag &= ~RX_FLAG_DECRYPTED;
	}

	/* rate_idx: index of data rate into band's
	 * supported rates or MCS index if HT rates
	 * are use (RX_FLAG_HT)
	 */
	/* Notice: this is diff with windows define */
	rx_status->rate_idx = rtlwifi_rate_mapping(
		hw, status->is_ht, status->is_vht, status->rate);

	rx_status->mactime = status->timestamp_low;

	_rtl8822be_translate_rx_signal_stuff(hw, skb, status, p_phystrpt);

	/* below info. are filled by _rtl8822be_translate_rx_signal_stuff() */
	if (!p_phystrpt)
		goto label_no_physt;

	rx_status->signal = status->recvsignalpower;

	if (status->rx_packet_bw == HT_CHANNEL_WIDTH_20_40)
		rx_status->bw = RATE_INFO_BW_40;
	else if (status->rx_packet_bw == HT_CHANNEL_WIDTH_80)
		rx_status->bw = RATE_INFO_BW_80;

label_no_physt:

	return true;
}