summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ralink/rt2x00/rt2x00mac.c')
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00mac.c79
1 files changed, 46 insertions, 33 deletions
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
index 2825560e2424..3bc0c1c906c9 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
<http://rt2x00.serialmonkey.com>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
@@ -176,11 +165,20 @@ int rt2x00mac_start(struct ieee80211_hw *hw)
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
+ if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
+ /*
+ * This is special case for ieee80211_restart_hw(), otherwise
+ * mac80211 never call start() two times in row without stop();
+ */
+ set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
+ rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
+ rt2x00lib_stop(rt2x00dev);
+ }
return rt2x00lib_start(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_start);
-void rt2x00mac_stop(struct ieee80211_hw *hw)
+void rt2x00mac_stop(struct ieee80211_hw *hw, bool suspend)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -191,6 +189,17 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
+void
+rt2x00mac_reconfig_complete(struct ieee80211_hw *hw,
+ enum ieee80211_reconfig_type reconfig_type)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+
+ if (reconfig_type == IEEE80211_RECONFIG_TYPE_RESTART)
+ clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_reconfig_complete);
+
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -295,7 +304,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
-int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
+int rt2x00mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
@@ -316,7 +325,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
*/
rt2x00queue_stop_queue(rt2x00dev->rx);
- /* Do not race with with link tuner. */
+ /* Do not race with link tuner. */
mutex_lock(&rt2x00dev->conf_mutex);
/*
@@ -399,8 +408,7 @@ static void rt2x00mac_set_tim_iter(void *data, u8 *mac,
if (vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC &&
- vif->type != NL80211_IFTYPE_MESH_POINT &&
- vif->type != NL80211_IFTYPE_WDS)
+ vif->type != NL80211_IFTYPE_MESH_POINT)
return;
set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags);
@@ -459,7 +467,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
- if (!rt2x00_has_cap_hw_crypto(rt2x00dev))
+ /* The hardware can't do MFP */
+ if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || (sta && sta->mfp))
return -EOPNOTSUPP;
/*
@@ -565,7 +574,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
- u32 changes)
+ u64 changes)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_intf *intf = vif_to_intf(vif);
@@ -589,6 +598,17 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
*/
if (changes & BSS_CHANGED_BEACON_ENABLED) {
mutex_lock(&intf->beacon_skb_mutex);
+
+ /*
+ * Clear the 'enable_beacon' flag and clear beacon because
+ * the beacon queue has been stopped after hardware reset.
+ */
+ if (test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags) &&
+ intf->enable_beacon) {
+ intf->enable_beacon = false;
+ rt2x00queue_clear_beacon(rt2x00dev, vif);
+ }
+
if (!bss_conf->enable_beacon && intf->enable_beacon) {
rt2x00dev->intf_beaconing--;
intf->enable_beacon = false;
@@ -636,25 +656,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_ASSOC) {
rt2x00dev->link.count = 0;
- if (bss_conf->assoc)
+ if (vif->cfg.assoc)
rt2x00dev->intf_associated++;
else
rt2x00dev->intf_associated--;
rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
-
- clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
}
/*
- * Check for access point which do not support 802.11e . We have to
- * generate data frames sequence number in S/W for such AP, because
- * of H/W bug.
- */
- if (changes & BSS_CHANGED_QOS && !bss_conf->qos)
- set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
-
- /*
* When the erp information has changed, we should perform
* additional configuration steps. For all other changes we are done.
*/
@@ -666,7 +676,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u16 queue_idx,
+ struct ieee80211_vif *vif,
+ unsigned int link_id, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -729,7 +740,8 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
EXPORT_SYMBOL_GPL(rt2x00mac_flush);
-int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 tx_ant, u32 rx_ant)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct link_ant *ant = &rt2x00dev->link.ant;
@@ -774,7 +786,8 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
}
EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
-int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 *tx_ant, u32 *rx_ant)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct link_ant *ant = &rt2x00dev->link.ant;