u32 info_flags)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
struct sk_buff *next;
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
goto out_free;
- if (!IS_ERR_OR_NULL(sta)) {
+ if (IS_ERR(sta))
+ sta = NULL;
+
+ if (local->ops->wake_tx_queue) {
+ u16 queue = __ieee80211_select_queue(sdata, sta, skb);
+ skb_set_queue_mapping(skb, queue);
+ }
+
+ if (sta) {
struct ieee80211_fast_tx *fast_tx;
sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
return ieee80211_downgrade_queue(sdata, NULL, skb);
}
+u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta, struct sk_buff *skb)
+{
+ struct mac80211_qos_map *qos_map;
+ bool qos;
+
+ /* all mesh/ocb stations are required to support WME */
+ if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
+ sdata->vif.type == NL80211_IFTYPE_OCB)
+ qos = true;
+ else if (sta)
+ qos = sta->sta.wme;
+ else
+ qos = false;
+
+ if (!qos) {
+ skb->priority = 0; /* required for correct WPA/11i MIC */
+ return IEEE80211_AC_BE;
+ }
+
+ if (skb->protocol == sdata->control_port_protocol) {
+ skb->priority = 7;
+ goto downgrade;
+ }
+
+ /* use the data classifier to determine what 802.1d tag the
+ * data frame has */
+ qos_map = rcu_dereference(sdata->qos_map);
+ skb->priority = cfg80211_classify8021d(skb, qos_map ?
+ &qos_map->qos_map : NULL);
+
+ downgrade:
+ return ieee80211_downgrade_queue(sdata, sta, skb);
+}
+
+
/* Indicate which queue to use. */
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
struct ieee80211_local *local = sdata->local;
struct sta_info *sta = NULL;
const u8 *ra = NULL;
- bool qos = false;
- struct mac80211_qos_map *qos_map;
u16 ret;
+ /* when using iTXQ, we can do this later */
+ if (local->ops->wake_tx_queue)
+ return 0;
+
if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
skb->priority = 0; /* required for correct WPA/11i MIC */
return 0;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
sta = rcu_dereference(sdata->u.vlan.sta);
- if (sta) {
- qos = sta->sta.wme;
+ if (sta)
break;
- }
/* fall through */
case NL80211_IFTYPE_AP:
ra = skb->data;
case NL80211_IFTYPE_WDS:
ra = sdata->u.wds.remote_addr;
break;
-#ifdef CONFIG_MAC80211_MESH
- case NL80211_IFTYPE_MESH_POINT:
- qos = true;
- break;
-#endif
case NL80211_IFTYPE_STATION:
/* might be a TDLS station */
sta = sta_info_get(sdata, skb->data);
if (sta)
- qos = sta->sta.wme;
+ break;
ra = sdata->u.mgd.bssid;
break;
case NL80211_IFTYPE_ADHOC:
ra = skb->data;
break;
- case NL80211_IFTYPE_OCB:
- /* all stations are required to support WME */
- qos = true;
- break;
default:
break;
}
- if (!sta && ra && !is_multicast_ether_addr(ra)) {
+ if (!sta && ra && !is_multicast_ether_addr(ra))
sta = sta_info_get(sdata, ra);
- if (sta)
- qos = sta->sta.wme;
- }
- if (!qos) {
- skb->priority = 0; /* required for correct WPA/11i MIC */
- ret = IEEE80211_AC_BE;
- goto out;
- }
+ ret = __ieee80211_select_queue(sdata, sta, skb);
- if (skb->protocol == sdata->control_port_protocol) {
- skb->priority = 7;
- goto downgrade;
- }
-
- /* use the data classifier to determine what 802.1d tag the
- * data frame has */
- qos_map = rcu_dereference(sdata->qos_map);
- skb->priority = cfg80211_classify8021d(skb, qos_map ?
- &qos_map->qos_map : NULL);
-
- downgrade:
- ret = ieee80211_downgrade_queue(sdata, sta, skb);
- out:
rcu_read_unlock();
return ret;
}