static void rtl_get_rate( void *ppriv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc ) { struct rtl_priv *rtlpriv = ppriv; struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB( skb ); struct ieee80211_tx_rate *rates = tx_info->control.rates; __le16 fc = rtl_get_fc( skb ); u8 try_per_rate, i, rix; bool not_data = !ieee80211_is_data( fc ); if ( rate_control_send_low( sta, priv_sta, txrc ) ) return; rix = _rtl_rc_get_highest_rix( rtlpriv, sta, skb, not_data ); try_per_rate = 1; _rtl_rc_rate_set_series( rtlpriv, sta, &rates[0], txrc, try_per_rate, rix, 1, not_data ); if ( !not_data ) { for ( i = 1; i < 4; i++ ) _rtl_rc_rate_set_series( rtlpriv, sta, &rates[i], txrc, i, ( rix - i ), 1, not_data ); } }
static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_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; return skb->priority; }
/*mac80211 Rate Control callbacks*/ static void rtl_tx_status(void *ppriv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { struct rtl_priv *rtlpriv = ppriv; struct rtl_mac *mac = rtl_mac(rtlpriv); struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = rtl_get_fc(skb); struct rtl_sta_info *sta_entry; if (!priv_sta || !ieee80211_is_data(fc)) return; if (rtl_is_special_data(mac->hw, skb, true)) return; if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) return; if (sta) { /* Check if aggregation has to be enabled for this tid */ sta_entry = (struct rtl_sta_info *) sta->drv_priv; if ((sta->ht_cap.ht_supported == true) && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { if (ieee80211_is_data_qos(fc)) { u8 tid = rtl_get_tid(skb); if (_rtl_tx_aggr_check(rtlpriv, sta_entry, tid)) { sta_entry->tids[tid].agg.agg_state = RTL_AGG_PROGRESS; /*<delete in kernel start>*/ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) /*<delete in kernel end>*/ ieee80211_start_tx_ba_session(sta, tid, 5000); /*<delete in kernel start>*/ #else ieee80211_start_tx_ba_session(sta, tid); #endif /*<delete in kernel end>*/ } } } } }
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; }
bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw); __le16 fc = rtl_get_fc(skb); if (rtlpriv->dm.supp_phymode_switch && mac->link_state < MAC80211_LINKED && (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { if (rtlpriv->cfg->ops->check_switch_to_dmdp) rtlpriv->cfg->ops->check_switch_to_dmdp(hw); } if (ieee80211_is_auth(fc)) { RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); rtl_ips_nic_on(hw); mac->link_state = MAC80211_LINKING; /* Dual mac */ rtlpriv->phy.need_iqk = true; } return true; }
/*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 rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); __le16 fc = rtl_get_fc(skb); u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; if (!ieee80211_is_data(fc)) return false; 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) { schedule_work(&rtlpriv-> works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } } } else if (ETH_P_ARP == ether_type) { if (is_tx) { schedule_work(&rtlpriv->works.lps_leave_work); 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) { schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (ETH_P_IPV6 == ether_type) { /* IPv6 */ return true; } return false; }