mac80211: move QoS-enable to BSS info
authorJohannes Berg <johannes@sipsolutions.net>
Mon, 19 Jul 2010 14:39:04 +0000 (16:39 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 20 Jul 2010 20:02:58 +0000 (16:02 -0400)
Ever since

commit e1b3ec1a2a336c328c336cfa5485a5f0484cc90d
Author: Stanislaw Gruszka <sgruszka@redhat.com>
Date:   Mon Mar 29 12:18:34 2010 +0200

    mac80211: explicitly disable/enable QoS

mac80211 is telling drivers, in particular
iwlwifi, whether QoS is enabled or not.

However, this is only relevant for station mode,
since only then will any device send nullfunc
frames and need to know whether they should be
QoS frames or not. In other modes, there are
(currently) no frames the device is supposed to
send.

When you now consider virtual interfaces, it
becomes apparent that the current mechanism is
inadequate since it enables/disables QoS on a
global scale, where for nullfunc frames it has
to be on a per-interface scale.

Due to the above considerations, we can change
the way mac80211 advertises the QoS state to
drivers to only ever advertise it as "off" in
station mode, and make it a per-BSS setting.

Tested-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-core.c
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/mlme.c
net/mac80211/util.c

index f73eb08a949450959bd2d403346781af6fe28ff0..676d49df77ed28ffb19c9662b3c06705e26dde01 100644 (file)
@@ -1763,6 +1763,15 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->mutex);
 
+       if (changes & BSS_CHANGED_QOS) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&priv->lock, flags);
+               priv->qos_data.qos_active = bss_conf->qos;
+               iwl_update_qos(priv);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+
        if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
                dev_kfree_skb(priv->ibss_beacon);
                priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
@@ -2134,15 +2143,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
                iwl_set_tx_power(priv, conf->power_level, false);
        }
 
-       if (changed & IEEE80211_CONF_CHANGE_QOS) {
-               bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS);
-
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->qos_data.qos_active = qos_active;
-               iwl_update_qos(priv);
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
-
        if (!iwl_is_ready(priv)) {
                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
                goto out;
index 7f256e23c57f5aece4a14b069790cc3b920a2d5f..20d372edec29dce5586b45684fb71532c89e541f 100644 (file)
@@ -147,6 +147,8 @@ struct ieee80211_low_level_stats {
  * @BSS_CHANGED_CQM: Connection quality monitor config changed
  * @BSS_CHANGED_IBSS: IBSS join status changed
  * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
+ * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
+ *     that it is only ever disabled for station mode.
  */
 enum ieee80211_bss_change {
        BSS_CHANGED_ASSOC               = 1<<0,
@@ -162,6 +164,7 @@ enum ieee80211_bss_change {
        BSS_CHANGED_CQM                 = 1<<10,
        BSS_CHANGED_IBSS                = 1<<11,
        BSS_CHANGED_ARP_FILTER          = 1<<12,
+       BSS_CHANGED_QOS                 = 1<<13,
 
        /* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -217,6 +220,7 @@ enum ieee80211_bss_change {
  *     filter ARP queries based on the @arp_addr_list, if disabled, the
  *     hardware must not perform any ARP filtering. Note, that the filter will
  *     be enabled also in promiscuous mode.
+ * @qos: This is a QoS-enabled BSS.
  */
 struct ieee80211_bss_conf {
        const u8 *bssid;
@@ -240,6 +244,7 @@ struct ieee80211_bss_conf {
        __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
        u8 arp_addr_cnt;
        bool arp_filter_enabled;
+       bool qos;
 };
 
 /**
@@ -620,15 +625,11 @@ struct ieee80211_rx_status {
  *     may turn the device off as much as possible. Typically, this flag will
  *     be set when an interface is set UP but not associated or scanning, but
  *     it can also be unset in that case when monitor interfaces are active.
- * @IEEE80211_CONF_QOS: Enable 802.11e QoS also know as WMM (Wireless
- *      Multimedia). On some drivers (iwlwifi is one of know) we have
- *      to enable/disable QoS explicitly.
  */
 enum ieee80211_conf_flags {
        IEEE80211_CONF_MONITOR          = (1<<0),
        IEEE80211_CONF_PS               = (1<<1),
        IEEE80211_CONF_IDLE             = (1<<2),
-       IEEE80211_CONF_QOS              = (1<<3),
 };
 
 
@@ -643,7 +644,6 @@ enum ieee80211_conf_flags {
  * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
  * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
  * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
- * @IEEE80211_CONF_CHANGE_QOS: Quality of service was enabled or disabled
  */
 enum ieee80211_conf_changed {
        IEEE80211_CONF_CHANGE_SMPS              = BIT(1),
@@ -654,7 +654,6 @@ enum ieee80211_conf_changed {
        IEEE80211_CONF_CHANGE_CHANNEL           = BIT(6),
        IEEE80211_CONF_CHANGE_RETRY_LIMITS      = BIT(7),
        IEEE80211_CONF_CHANGE_IDLE              = BIT(8),
-       IEEE80211_CONF_CHANGE_QOS               = BIT(9),
 };
 
 /**
index 5b8b4460b69f95f69dcd9e9786bb02d2b459aaa5..35b07ea0633aee8edc6d72a2d49ef874961c7def 100644 (file)
@@ -1154,10 +1154,6 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
                return -EINVAL;
        }
 
-       /* enable WMM or activate new settings */
-       local->hw.conf.flags |= IEEE80211_CONF_QOS;
-       drv_config(local, IEEE80211_CONF_CHANGE_QOS);
-
        return 0;
 }
 
index d1962650b254e4a44bf7dbf6232750ca551bd793..7a4e4bffbc7158a8fda8de7c2ee336eb8da54b3e 100644 (file)
@@ -698,10 +698,11 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
 
 /* MLME */
 static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
-                                    struct ieee80211_if_managed *ifmgd,
+                                    struct ieee80211_sub_if_data *sdata,
                                     u8 *wmm_param, size_t wmm_param_len)
 {
        struct ieee80211_tx_queue_params params;
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        size_t left;
        int count;
        u8 *pos, uapsd_queues = 0;
@@ -790,8 +791,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
        }
 
        /* enable WMM or activate new settings */
-       local->hw.conf.flags |= IEEE80211_CONF_QOS;
-       drv_config(local, IEEE80211_CONF_CHANGE_QOS);
+       sdata->vif.bss_conf.qos = true;
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
 }
 
 static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@ -1325,7 +1326,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
        }
 
        if (elems.wmm_param)
-               ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
+               ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
                                         elems.wmm_param_len);
        else
                ieee80211_set_wmm_default(sdata);
@@ -1597,7 +1598,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
                                      true);
 
-               ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
+               ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
                                         elems.wmm_param_len);
        }
 
index a54cf146ed5066c993f501f67a6c332a68024509..7947921773760d170598be47c9cb1d2a32e1d9a5 100644 (file)
@@ -803,8 +803,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
 
        /* after reinitialize QoS TX queues setting to default,
         * disable QoS at all */
-       local->hw.conf.flags &= ~IEEE80211_CONF_QOS;
-       drv_config(local, IEEE80211_CONF_CHANGE_QOS);
+       sdata->vif.bss_conf.qos = sdata->vif.type != NL80211_IFTYPE_STATION;
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
 }
 
 void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
@@ -1161,7 +1161,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                          BSS_CHANGED_BASIC_RATES |
                          BSS_CHANGED_BEACON_INT |
                          BSS_CHANGED_BSSID |
-                         BSS_CHANGED_CQM;
+                         BSS_CHANGED_CQM |
+                         BSS_CHANGED_QOS;
 
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_STATION: