mac80211: make beacon filtering per virtual interface
authorJohannes Berg <johannes.berg@intel.com>
Thu, 19 Jan 2012 08:29:57 +0000 (09:29 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 27 Jan 2012 19:56:53 +0000 (14:56 -0500)
Due to firmware limitations, we may not be able to
support beacon filtering on all virtual interfaces.
To allow this in mac80211, introduce per-interface
driver capability flags that the driver sets when
an interface is added.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/p54/main.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/wl1251/main.c
drivers/net/wireless/wl12xx/main.c
include/net/mac80211.h
net/mac80211/debugfs.c
net/mac80211/mlme.c

index af2ca1a9c7d32ed014f11d1390e5c1d8bcf09fb6..40f4eb7da7b296e3d01227f625a24f4be401fdd6 100644 (file)
@@ -228,6 +228,8 @@ static int p54_add_interface(struct ieee80211_hw *dev,
 {
        struct p54_common *priv = dev->priv;
 
+       vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
        mutex_lock(&priv->conf_mutex);
        if (priv->mode != NL80211_IFTYPE_MONITOR) {
                mutex_unlock(&priv->conf_mutex);
@@ -734,7 +736,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
                     IEEE80211_HW_SIGNAL_DBM |
                     IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_PS_NULLFUNC_STACK |
-                    IEEE80211_HW_BEACON_FILTER |
                     IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
        dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
index 6f80142580fda3f374e1b140fd459b5ec4ed53c7..ff3e393bc1041c6d416f28186e8e6eeb5cf5a58f 100644 (file)
@@ -309,7 +309,6 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
        /* <5> set hw caps */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
            IEEE80211_HW_RX_INCLUDES_FCS |
-           IEEE80211_HW_BEACON_FILTER |
            IEEE80211_HW_AMPDU_AGGREGATION |
            IEEE80211_HW_CONNECTION_MONITOR |
            /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
index d6e37e6a1d53f2ee6e2f6223d36aafe3f34f195f..0ee01ab2e4f6f1d81745af6e717510c3e8a7c5cd 100644 (file)
@@ -112,6 +112,8 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        int err = 0;
 
+       vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
        if (mac->vif) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
                         "vif has been set!! mac->vif = 0x%p\n", mac->vif);
index ba3268ea81fe57563c9f0f95a293773c21f68ffe..86540db6f1a8d2ddcb0c9436ae2646af4f2b52e0 100644 (file)
@@ -514,6 +514,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
        struct wl1251 *wl = hw->priv;
        int ret = 0;
 
+       vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
        wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
                     vif->type, vif->addr);
 
@@ -1338,7 +1340,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
 
        wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
                IEEE80211_HW_SUPPORTS_PS |
-               IEEE80211_HW_BEACON_FILTER |
                IEEE80211_HW_SUPPORTS_UAPSD |
                IEEE80211_HW_SUPPORTS_CQM_RSSI;
 
index d5f55a149de5e43216ad46c7ebf0d4825e9d0628..afc5381f2870b5660400c014350066d4e1bdf35c 100644 (file)
@@ -2060,6 +2060,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
        u8 role_type;
        bool booted = false;
 
+       vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
        wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
                     ieee80211_vif_type_p2p(vif), vif->addr);
 
@@ -4898,7 +4900,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
        wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval;
 
        wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
-               IEEE80211_HW_BEACON_FILTER |
                IEEE80211_HW_SUPPORTS_PS |
                IEEE80211_HW_SUPPORTS_UAPSD |
                IEEE80211_HW_HAS_RATE_CONTROL |
index d49928ba5d09fa379fd5db91ea173cfe08d57475..ae8db247bdeb83e08378d9933700ee938e04e96e 100644 (file)
@@ -851,6 +851,16 @@ struct ieee80211_channel_switch {
        u8 count;
 };
 
+/**
+ * enum ieee80211_vif_flags - virtual interface flags
+ *
+ * @IEEE80211_VIF_BEACON_FILTER: the device performs beacon filtering
+ *     on this virtual interface to avoid unnecessary CPU wakeups
+ */
+enum ieee80211_vif_flags {
+       IEEE80211_VIF_BEACON_FILTER             = BIT(0),
+};
+
 /**
  * struct ieee80211_vif - per-interface data
  *
@@ -863,6 +873,10 @@ struct ieee80211_channel_switch {
  * @addr: address of this interface
  * @p2p: indicates whether this AP or STA interface is a p2p
  *     interface, i.e. a GO or p2p-sta respectively
+ * @driver_flags: flags/capabilities the driver has for this interface,
+ *     these need to be set (or cleared) when the interface is added
+ *     or, if supported by the driver, the interface type is changed
+ *     at runtime, mac80211 will never touch this field
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void *).
  */
@@ -871,6 +885,7 @@ struct ieee80211_vif {
        struct ieee80211_bss_conf bss_conf;
        u8 addr[ETH_ALEN];
        bool p2p;
+       u32 driver_flags;
        /* must be last */
        u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
 };
@@ -1079,10 +1094,6 @@ enum sta_notify_cmd {
  * @IEEE80211_HW_MFP_CAPABLE:
  *     Hardware supports management frame protection (MFP, IEEE 802.11w).
  *
- * @IEEE80211_HW_BEACON_FILTER:
- *     Hardware supports dropping of irrelevant beacon frames to
- *     avoid waking up cpu.
- *
  * @IEEE80211_HW_SUPPORTS_STATIC_SMPS:
  *     Hardware supports static spatial multiplexing powersave,
  *     ie. can turn off all but one chain even on HT connections
@@ -1150,7 +1161,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_PS_NULLFUNC_STACK                  = 1<<11,
        IEEE80211_HW_SUPPORTS_DYNAMIC_PS                = 1<<12,
        IEEE80211_HW_MFP_CAPABLE                        = 1<<13,
-       IEEE80211_HW_BEACON_FILTER                      = 1<<14,
+       /* reuse bit 14 */
        IEEE80211_HW_SUPPORTS_STATIC_SMPS               = 1<<15,
        IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS              = 1<<16,
        IEEE80211_HW_SUPPORTS_UAPSD                     = 1<<17,
@@ -1446,8 +1457,8 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  * way the host will only receive beacons where some relevant information
  * (for example ERP protection or WMM settings) have changed.
  *
- * Beacon filter support is advertised with the %IEEE80211_HW_BEACON_FILTER
- * hardware capability. The driver needs to enable beacon filter support
+ * Beacon filter support is advertised with the %IEEE80211_VIF_BEACON_FILTER
+ * interface capability. The driver needs to enable beacon filter support
  * whenever power save is enabled, that is %IEEE80211_CONF_PS is set. When
  * power save is enabled, the stack will not check for beacon loss and the
  * driver needs to notify about loss of beacons with ieee80211_beacon_loss().
@@ -3316,7 +3327,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  *
- * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTER and
+ * When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER and
  * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the
  * hardware is not receiving beacons with this function.
  */
@@ -3327,7 +3338,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  *
- * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTER, and
+ * When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER, and
  * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver
  * needs to inform if the connection to the AP has been lost.
  *
index 90baea53e7c56572df7562d201237fed48ef49e9..e8868dae1c01cc72d185ca63a8eb3693f38e63e2 100644 (file)
@@ -247,8 +247,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
                sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
        if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
                sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
-       if (local->hw.flags & IEEE80211_HW_BEACON_FILTER)
-               sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n");
        if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS)
                sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n");
        if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
index 95d3964fc080a15cb84c039e1194da47672fb60c..b51eb49d8525c799c039cc464226cbe483c1350c 100644 (file)
@@ -127,7 +127,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd,
 
 void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
 {
-       if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
+       if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
                return;
 
        mod_timer(&sdata->u.mgd.bcn_mon_timer,