static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) { __le16 fc = rtl_get_fc(skb); if (unlikely(ieee80211_is_beacon(fc))) return QSLT_BEACON; if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) return QSLT_MGNT; if (ieee80211_is_nullfunc(fc)) return QSLT_HIGH; return skb->priority; }
static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth) { struct ieee80211_hdr *hdr = (void *)skb->data; struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); if (!is_eth && ieee80211_is_mgmt(hdr->frame_control)) return HTT_DATA_TX_EXT_TID_MGMT; else if (ieee80211_is_nullfunc(hdr->frame_control)) return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; else if (cb->flags & ATH10K_SKB_F_QOS) return skb->priority % IEEE80211_QOS_CTL_TID_MASK; else return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; }
static u8 _rtl92se_map_hwqueue_to_fwqueue( struct sk_buff *skb, u8 skb_queue ) { __le16 fc = rtl_get_fc( skb ); if ( unlikely( ieee80211_is_beacon( fc ) ) ) return QSLT_BEACON; if ( ieee80211_is_mgmt( fc ) || ieee80211_is_ctl( fc ) ) return QSLT_MGNT; if ( ieee80211_is_nullfunc( fc ) ) return QSLT_HIGH; /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use * queue V0 at priority 7; however, the RTL8192SE appears to have * that queue at priority 6 */ if ( skb->priority == 7 ) return QSLT_VO; return skb->priority; }
/*should call before software enc*/ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); u16 fc = le16_to_cpu(hdr->frame_control); u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; if (!ieee80211_is_data(fc)) goto end; if (ieee80211_is_nullfunc(fc)) return true; ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); ether_type = ntohs(ether_type); if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { struct udphdr *udp = (struct udphdr *)((u8 *) ip + (ip->ihl << 2)); if (((((u8 *) udp)[1] == 68) && (((u8 *) udp)[3] == 67)) || ((((u8 *) udp)[1] == 67) && (((u8 *) udp)[3] == 68))) { /* * 68 : UDP BOOTP client * 67 : UDP BOOTP server */ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, ("dhcp %s !!\n", (is_tx) ? "Tx" : "Rx")); if (is_tx) { rtl_lps_leave(hw); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } } } else if (ETH_P_ARP == ether_type) { if (is_tx) { rtl_lps_leave(hw); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (ETH_P_PAE == ether_type) { RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, ("802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx")); if (is_tx) { rtl_lps_leave(hw); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (0x86DD == ether_type) { return true; } end: return false; }
void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct ieee80211_rate *txrate; __le16 fc = hdr->frame_control; txrate = ieee80211_get_tx_rate(hw, info); if (txrate) tcb_desc->hw_rate = txrate->hw_value; else tcb_desc->hw_rate = 0; if (ieee80211_is_data(fc)) { /* *we set data rate INX 0 *in rtl_rc.c if skb is special data or *mgt which need low data rate. */ /* *So tcb_desc->hw_rate is just used for *special data and mgt frames */ if (info->control.rates[0].idx == 0 || ieee80211_is_nullfunc(fc)) { tcb_desc->use_driver_rate = true; tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; tcb_desc->disable_ratefallback = 1; } else { /* *because hw will nerver use hw_rate *when tcb_desc->use_driver_rate = false *so we never set highest N rate here, *and N rate will all be controlled by FW *when tcb_desc->use_driver_rate = false */ if (sta && (sta->ht_cap.ht_supported)) { tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); } else { if (rtlmac->mode == WIRELESS_MODE_B) { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; } else { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; } } } if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->multicast = 1; else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->broadcast = 1; _rtl_txrate_selectmode(hw, sta, tcb_desc); _rtl_query_bandwidth_mode(hw, sta, tcb_desc); _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); _rtl_query_shortgi(hw, sta, tcb_desc, info); _rtl_query_protection_mode(hw, tcb_desc, info); } else { tcb_desc->use_driver_rate = true; tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; tcb_desc->disable_ratefallback = 1; tcb_desc->mac_id = 0; tcb_desc->packet_bw = false; } }
void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *pbd_desc_tx, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; u8 reserved_macid = 0; u8 fw_qsel = rtl92s_map_hwqueue_to_fwqueue(skb, hw_queue); bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); bool lastseg = (!(hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))); dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); u8 bw_40 = 0; if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "DMA mapping error\n"); return; } if (mac->opmode == NL80211_IFTYPE_STATION) { bw_40 = mac->bw_40; } else if (mac->opmode == NL80211_IFTYPE_AP || mac->opmode == NL80211_IFTYPE_ADHOC) { if (sta) bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; } seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { firstseg = true; lastseg = true; } if (firstseg) { if (rtlpriv->dm.useramask) { /* set txdesc macId */ if (ptcb_desc->mac_id < 32) { SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); reserved_macid |= ptcb_desc->mac_id; } } SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= DESC_RATEMCS0) ? 1 : 0)); if (rtlhal->version == VERSION_8192S_ACUT) { if (ptcb_desc->hw_rate == DESC_RATE1M || ptcb_desc->hw_rate == DESC_RATE2M || ptcb_desc->hw_rate == DESC_RATE5_5M || ptcb_desc->hw_rate == DESC_RATE11M) { ptcb_desc->hw_rate = DESC_RATE12M; } } SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) SET_TX_DESC_TX_SHORT(pdesc, 0); /* Aggregation related */ if (info->flags & IEEE80211_TX_CTL_AMPDU) SET_TX_DESC_AGG_ENABLE(pdesc, 1); /* For AMPDU, we must insert SSN into TX_DESC */ SET_TX_DESC_SEQ(pdesc, seq_number); /* Protection mode related */ /* For 92S, if RTS/CTS are set, HW will execute RTS. */ /* We choose only one protection mode to execute */ SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && !ptcb_desc->cts_enable) ? 1 : 0)); SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= DESC_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); /* Set Bandwidth and sub-channel settings. */ if (bw_40) { if (ptcb_desc->packet_bw) { SET_TX_DESC_TX_BANDWIDTH(pdesc, 1); /* use duplicated mode */ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); } else { SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); SET_TX_DESC_TX_SUB_CARRIER(pdesc, mac->cur_40_prime_sc); } } else { SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); } /* 3 Fill necessary field in First Descriptor */ /*DWORD 0*/ SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_OFFSET(pdesc, 32); SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); /*DWORD 1*/ SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index); /* Fill security related */ if (info->control.hw_key) { struct ieee80211_key_conf *keyconf; keyconf = info->control.hw_key; switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: SET_TX_DESC_SEC_TYPE(pdesc, 0x1); break; case WLAN_CIPHER_SUITE_TKIP: SET_TX_DESC_SEC_TYPE(pdesc, 0x2); break; case WLAN_CIPHER_SUITE_CCMP: SET_TX_DESC_SEC_TYPE(pdesc, 0x3); break; default: SET_TX_DESC_SEC_TYPE(pdesc, 0x0); break; } } /* Set Packet ID */ SET_TX_DESC_PACKET_ID(pdesc, 0); /* We will assign magement queue to BK. */ SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); /* Alwasy enable all rate fallback range */ SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); /* Fix: I don't know why hw use 6.5M to tx when set it */ SET_TX_DESC_USER_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); /* Set NON_QOS bit. */ if (!ieee80211_is_data_qos(fc)) SET_TX_DESC_NON_QOS(pdesc, 1); } /* Fill fields that are required to be initialized * in all of the descriptors */ /*DWORD 0 */ SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); /* DWORD 7 */ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); /* DOWRD 8 */ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); }
void rtl8822be_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *pbd_desc_tx, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_phy *rtlphy = &rtlpriv->phy; u8 *pdesc = (u8 *)pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; u8 fw_qsel = _rtl8822be_map_hwqueue_to_fwqueue(skb, hw_queue); bool firstseg = ((hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); bool lastseg = ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); dma_addr_t mapping; u8 short_gi = 0; seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); /* reserve 8 byte for AMPDU early mode */ if (rtlhal->earlymode_enable) { skb_push(skb, EM_HDR_LEN); memset(skb->data, 0, EM_HDR_LEN); } mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "DMA mapping error"); return; } if (pbd_desc_tx) rtl8822be_pre_fill_tx_bd_desc(hw, pbd_desc_tx, pdesc, hw_queue, skb, mapping); if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { firstseg = true; lastseg = true; } if (firstseg) { if (rtlhal->earlymode_enable) { SET_TX_DESC_PKT_OFFSET(pdesc, 1); SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + EM_HDR_LEN); if (ptcb_desc->empkt_num) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "Insert 8 byte.pTcb->EMPktNum:%d\n", ptcb_desc->empkt_num); _rtl8822be_insert_emcontent(ptcb_desc, (u8 *)(skb->data)); } } else { SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); } /* tx report */ rtl_get_tx_report(ptcb_desc, pdesc, hw); if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G && ptcb_desc->hw_rate < DESC_RATE6M) { RT_TRACE(rtlpriv, COMP_SEND, DBG_WARNING, "hw_rate=0x%X is invalid in 5G\n", ptcb_desc->hw_rate); ptcb_desc->hw_rate = DESC_RATE6M; } SET_TX_DESC_DATARATE(pdesc, ptcb_desc->hw_rate); if (ptcb_desc->hw_rate > DESC_RATEMCS0) short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; else short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; if (info->flags & IEEE80211_TX_CTL_AMPDU) { SET_TX_DESC_AGG_EN(pdesc, 1); SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x1F); } SET_TX_DESC_SW_SEQ(pdesc, seq_number); SET_TX_DESC_RTSEN(pdesc, ((ptcb_desc->rts_enable && !ptcb_desc->cts_enable) ? 1 : 0)); SET_TX_DESC_HW_RTS_EN(pdesc, 0); SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); SET_TX_DESC_RTSRATE(pdesc, ptcb_desc->rts_rate); SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT( pdesc, ((ptcb_desc->rts_rate <= DESC_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); if (ptcb_desc->tx_enable_sw_calc_duration) SET_TX_DESC_NAVUSEHDR(pdesc, 1); SET_TX_DESC_DATA_BW(pdesc, rtl8822be_bw_mapping(hw, ptcb_desc)); SET_TX_DESC_DATA_SC(pdesc, rtl8822be_sc_mapping(hw, ptcb_desc)); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); } if (info->control.hw_key) { struct ieee80211_key_conf *key = info->control.hw_key; switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: SET_TX_DESC_SEC_TYPE(pdesc, 0x1); break; case WLAN_CIPHER_SUITE_CCMP: SET_TX_DESC_SEC_TYPE(pdesc, 0x3); break; default: SET_TX_DESC_SEC_TYPE(pdesc, 0x0); break; } } SET_TX_DESC_QSEL(pdesc, fw_qsel); if (rtlphy->current_channel > 14) { /* OFDM 6M */ SET_TX_DESC_DATA_RTY_LOWEST_RATE(pdesc, 4); SET_TX_DESC_RTS_RTY_LOWEST_RATE(pdesc, 4); } else { /* CCK 1M */ SET_TX_DESC_DATA_RTY_LOWEST_RATE(pdesc, 0); SET_TX_DESC_RTS_RTY_LOWEST_RATE(pdesc, 0); } SET_TX_DESC_DISDATAFB(pdesc, ptcb_desc->disable_ratefallback ? 1 : 0); SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/ /* Set TxRate and RTSRate in TxDesc */ /* This prevent Tx initial rate of new-coming packets */ /* from being overwritten by retried packet rate.*/ if (!ptcb_desc->use_driver_rate) { /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ } if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "Enable RDG function.\n"); SET_TX_DESC_RDG_EN(pdesc, 1); SET_TX_DESC_HTC(pdesc, 1); } } SET_TX_DESC_PORT_ID(pdesc, 0); SET_TX_DESC_MULTIPLE_PORT(pdesc, 0); } SET_TX_DESC_LS(pdesc, (lastseg ? 1 : 0)); if (rtlpriv->dm.useramask) { SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); } else { SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); } SET_TX_DESC_MOREFRAG(pdesc, (lastseg ? 0 : 1)); if (ptcb_desc->multicast || ptcb_desc->broadcast) { SET_TX_DESC_BMC(pdesc, 1); /* BMC must be not AGG */ SET_TX_DESC_AGG_EN(pdesc, 0); } RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); /* debug purpose: used to check tx desc is correct or not */ /*rtlpriv->halmac.ops->halmac_chk_txdesc(rtlpriv, pdesc, * skb->len + USB_HWDESC_HEADER_LEN); */ }