diff options
Diffstat (limited to 'drivers/net/wireless/rsi/rsi_91x_mac80211.c')
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_mac80211.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 9427c9d7c9c7..c3bd3ca9cf83 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1746,6 +1746,119 @@ static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw) return 0; } +static const struct wiphy_wowlan_support rsi_wowlan_support = { + .flags = WIPHY_WOWLAN_ANY | + WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE, +}; + +static u16 rsi_wow_map_triggers(struct rsi_common *common, + struct cfg80211_wowlan *wowlan) +{ + u16 wow_triggers = 0; + + rsi_dbg(INFO_ZONE, "Mapping wowlan triggers\n"); + + if (wowlan->any) + wow_triggers |= RSI_WOW_ANY; + if (wowlan->magic_pkt) + wow_triggers |= RSI_WOW_MAGIC_PKT; + if (wowlan->disconnect) + wow_triggers |= RSI_WOW_DISCONNECT; + if (wowlan->gtk_rekey_failure || wowlan->eap_identity_req || + wowlan->four_way_handshake) + wow_triggers |= RSI_WOW_GTK_REKEY; + + return wow_triggers; +} + +int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan) +{ + struct rsi_common *common = adapter->priv; + u16 triggers = 0; + u16 rx_filter_word = 0; + struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf; + + rsi_dbg(INFO_ZONE, "Config WoWLAN to device\n"); + + if (WARN_ON(!wowlan)) { + rsi_dbg(ERR_ZONE, "WoW triggers not enabled\n"); + return -EINVAL; + } + + triggers = rsi_wow_map_triggers(common, wowlan); + if (!triggers) { + rsi_dbg(ERR_ZONE, "%s:No valid WoW triggers\n", __func__); + return -EINVAL; + } + if (!bss->assoc) { + rsi_dbg(ERR_ZONE, + "Cannot configure WoWLAN (Station not connected)\n"); + common->wow_flags |= RSI_WOW_NO_CONNECTION; + return 0; + } + rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers); + rsi_send_wowlan_request(common, triggers, 1); + + /** + * Increase the beacon_miss threshold & keep-alive timers in + * vap_update frame + */ + rsi_send_vap_dynamic_update(common); + + rx_filter_word = (ALLOW_DATA_ASSOC_PEER | DISALLOW_BEACONS); + rsi_send_rx_filter_frame(common, rx_filter_word); + common->wow_flags |= RSI_WOW_ENABLED; + + return 0; +} + +#ifdef CONFIG_PM +static int rsi_mac80211_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct rsi_hw *adapter = hw->priv; + struct rsi_common *common = adapter->priv; + + rsi_dbg(INFO_ZONE, "%s: mac80211 suspend\n", __func__); + mutex_lock(&common->mutex); + if (rsi_config_wowlan(adapter, wowlan)) { + rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); + mutex_unlock(&common->mutex); + return 1; + } + mutex_unlock(&common->mutex); + + return 0; +} + +static int rsi_mac80211_resume(struct ieee80211_hw *hw) +{ + u16 rx_filter_word = 0; + struct rsi_hw *adapter = hw->priv; + struct rsi_common *common = adapter->priv; + + common->wow_flags = 0; + + rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__); + + mutex_lock(&common->mutex); + rsi_send_wowlan_request(common, 0, 0); + + rx_filter_word = (ALLOW_DATA_ASSOC_PEER | ALLOW_CTRL_ASSOC_PEER | + ALLOW_MGMT_ASSOC_PEER); + rsi_send_rx_filter_frame(common, rx_filter_word); + mutex_unlock(&common->mutex); + + return 0; +} + +#endif + static const struct ieee80211_ops mac80211_ops = { .tx = rsi_mac80211_tx, .start = rsi_mac80211_start, @@ -1767,6 +1880,10 @@ static const struct ieee80211_ops mac80211_ops = { .rfkill_poll = rsi_mac80211_rfkill_poll, .remain_on_channel = rsi_mac80211_roc, .cancel_remain_on_channel = rsi_mac80211_cancel_roc, +#ifdef CONFIG_PM + .suspend = rsi_mac80211_suspend, + .resume = rsi_mac80211_resume, +#endif }; /** @@ -1850,6 +1967,7 @@ int rsi_mac80211_attach(struct rsi_common *common) wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; wiphy->reg_notifier = rsi_reg_notify; + wiphy->wowlan = &rsi_wowlan_support; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); /* Wi-Fi direct parameters */ |