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