Эх сурвалжийг харах

mac80211: make beacon filtering per virtual interface

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>
Johannes Berg 13 жил өмнө
parent
commit
c1288b1278

+ 2 - 1
drivers/net/wireless/p54/main.c

@@ -228,6 +228,8 @@ static int p54_add_interface(struct ieee80211_hw *dev,
 {
 {
 	struct p54_common *priv = dev->priv;
 	struct p54_common *priv = dev->priv;
 
 
+	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
 	mutex_lock(&priv->conf_mutex);
 	mutex_lock(&priv->conf_mutex);
 	if (priv->mode != NL80211_IFTYPE_MONITOR) {
 	if (priv->mode != NL80211_IFTYPE_MONITOR) {
 		mutex_unlock(&priv->conf_mutex);
 		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_SIGNAL_DBM |
 		     IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_PS_NULLFUNC_STACK |
 		     IEEE80211_HW_PS_NULLFUNC_STACK |
-		     IEEE80211_HW_BEACON_FILTER |
 		     IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 		     IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
 
 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |

+ 0 - 1
drivers/net/wireless/rtlwifi/base.c

@@ -309,7 +309,6 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 	/* <5> set hw caps */
 	/* <5> set hw caps */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_RX_INCLUDES_FCS |
 	    IEEE80211_HW_RX_INCLUDES_FCS |
-	    IEEE80211_HW_BEACON_FILTER |
 	    IEEE80211_HW_AMPDU_AGGREGATION |
 	    IEEE80211_HW_AMPDU_AGGREGATION |
 	    IEEE80211_HW_CONNECTION_MONITOR |
 	    IEEE80211_HW_CONNECTION_MONITOR |
 	    /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
 	    /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */

+ 2 - 0
drivers/net/wireless/rtlwifi/core.c

@@ -112,6 +112,8 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	int err = 0;
 	int err = 0;
 
 
+	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
 	if (mac->vif) {
 	if (mac->vif) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 "vif has been set!! mac->vif = 0x%p\n", mac->vif);
 			 "vif has been set!! mac->vif = 0x%p\n", mac->vif);

+ 2 - 1
drivers/net/wireless/wl1251/main.c

@@ -514,6 +514,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
 	struct wl1251 *wl = hw->priv;
 	struct wl1251 *wl = hw->priv;
 	int ret = 0;
 	int ret = 0;
 
 
+	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
 	wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
 	wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
 		     vif->type, vif->addr);
 		     vif->type, vif->addr);
 
 
@@ -1338,7 +1340,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
 
 
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_SUPPORTS_PS |
-		IEEE80211_HW_BEACON_FILTER |
 		IEEE80211_HW_SUPPORTS_UAPSD |
 		IEEE80211_HW_SUPPORTS_UAPSD |
 		IEEE80211_HW_SUPPORTS_CQM_RSSI;
 		IEEE80211_HW_SUPPORTS_CQM_RSSI;
 
 

+ 2 - 1
drivers/net/wireless/wl12xx/main.c

@@ -2060,6 +2060,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 	u8 role_type;
 	u8 role_type;
 	bool booted = false;
 	bool booted = false;
 
 
+	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
 	wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
 	wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
 		     ieee80211_vif_type_p2p(vif), vif->addr);
 		     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->max_listen_interval = wl->conf.conn.max_listen_interval;
 
 
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		IEEE80211_HW_BEACON_FILTER |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_SUPPORTS_UAPSD |
 		IEEE80211_HW_SUPPORTS_UAPSD |
 		IEEE80211_HW_HAS_RATE_CONTROL |
 		IEEE80211_HW_HAS_RATE_CONTROL |

+ 20 - 9
include/net/mac80211.h

@@ -851,6 +851,16 @@ struct ieee80211_channel_switch {
 	u8 count;
 	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
  * struct ieee80211_vif - per-interface data
  *
  *
@@ -863,6 +873,10 @@ struct ieee80211_channel_switch {
  * @addr: address of this interface
  * @addr: address of this interface
  * @p2p: indicates whether this AP or STA interface is a p2p
  * @p2p: indicates whether this AP or STA interface is a p2p
  *	interface, i.e. a GO or p2p-sta respectively
  *	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
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
  *	sizeof(void *).
  */
  */
@@ -871,6 +885,7 @@ struct ieee80211_vif {
 	struct ieee80211_bss_conf bss_conf;
 	struct ieee80211_bss_conf bss_conf;
 	u8 addr[ETH_ALEN];
 	u8 addr[ETH_ALEN];
 	bool p2p;
 	bool p2p;
+	u32 driver_flags;
 	/* must be last */
 	/* must be last */
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
 };
 };
@@ -1079,10 +1094,6 @@ enum sta_notify_cmd {
  * @IEEE80211_HW_MFP_CAPABLE:
  * @IEEE80211_HW_MFP_CAPABLE:
  *	Hardware supports management frame protection (MFP, IEEE 802.11w).
  *	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:
  * @IEEE80211_HW_SUPPORTS_STATIC_SMPS:
  *	Hardware supports static spatial multiplexing powersave,
  *	Hardware supports static spatial multiplexing powersave,
  *	ie. can turn off all but one chain even on HT connections
  *	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_PS_NULLFUNC_STACK			= 1<<11,
 	IEEE80211_HW_SUPPORTS_DYNAMIC_PS		= 1<<12,
 	IEEE80211_HW_SUPPORTS_DYNAMIC_PS		= 1<<12,
 	IEEE80211_HW_MFP_CAPABLE			= 1<<13,
 	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_STATIC_SMPS		= 1<<15,
 	IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS		= 1<<16,
 	IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS		= 1<<16,
 	IEEE80211_HW_SUPPORTS_UAPSD			= 1<<17,
 	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
  * way the host will only receive beacons where some relevant information
  * (for example ERP protection or WMM settings) have changed.
  * (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
  * 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
  * 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().
  * 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.
  * @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
  * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the
  * hardware is not receiving beacons with this function.
  * 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.
  * @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
  * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver
  * needs to inform if the connection to the AP has been lost.
  * needs to inform if the connection to the AP has been lost.
  *
  *

+ 0 - 2
net/mac80211/debugfs.c

@@ -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");
 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
 	if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
 	if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
 		sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
 		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)
 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS)
 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n");
 		sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n");
 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)

+ 1 - 1
net/mac80211/mlme.c

@@ -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)
 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;
 		return;
 
 
 	mod_timer(&sdata->u.mgd.bcn_mon_timer,
 	mod_timer(&sdata->u.mgd.bcn_mon_timer,