Commit c1288b12 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

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: default avatarJohannes Berg <johannes.berg@intel.com>
Acked-by: default avatarLuciano Coelho <coelho@ti.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 47d505cc
...@@ -228,6 +228,8 @@ static int p54_add_interface(struct ieee80211_hw *dev, ...@@ -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) ...@@ -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) |
......
...@@ -309,7 +309,6 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) ...@@ -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 | */
......
...@@ -112,6 +112,8 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, ...@@ -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);
......
...@@ -514,6 +514,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, ...@@ -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) ...@@ -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;
......
...@@ -2060,6 +2060,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ...@@ -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) ...@@ -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 |
......
...@@ -851,6 +851,16 @@ struct ieee80211_channel_switch { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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 * Beacon filter support is advertised with the %IEEE80211_VIF_BEACON_FILTER
* hardware capability. The driver needs to enable beacon filter support * 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, ...@@ -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); ...@@ -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.
* *
......
...@@ -247,8 +247,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, ...@@ -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)
......
...@@ -127,7 +127,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd, ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment