aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath10k/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/mac.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c143
1 files changed, 101 insertions, 42 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index d1b7edba5e49..3029f257a19a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -569,10 +569,14 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
case NL80211_CHAN_WIDTH_80:
phymode = MODE_11AC_VHT80;
break;
+ case NL80211_CHAN_WIDTH_160:
+ phymode = MODE_11AC_VHT160;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ phymode = MODE_11AC_VHT80_80;
+ break;
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
- case NL80211_CHAN_WIDTH_80P80:
- case NL80211_CHAN_WIDTH_160:
phymode = MODE_UNKNOWN;
break;
}
@@ -971,6 +975,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
arg.vdev_id = vdev_id;
arg.channel.freq = channel->center_freq;
arg.channel.band_center_freq1 = chandef->center_freq1;
+ arg.channel.band_center_freq2 = chandef->center_freq2;
/* TODO setup this dynamically, what in case we
don't have any vifs? */
@@ -1417,6 +1422,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
arg.channel.freq = chandef->chan->center_freq;
arg.channel.band_center_freq1 = chandef->center_freq1;
+ arg.channel.band_center_freq2 = chandef->center_freq2;
arg.channel.mode = chan_to_phymode(chandef);
arg.channel.min_power = 0;
@@ -1987,7 +1993,7 @@ static void ath10k_mac_handle_beacon_iter(void *data, u8 *mac,
{
struct sk_buff *skb = data;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (vif->type != NL80211_IFTYPE_STATION)
return;
@@ -2010,7 +2016,7 @@ static void ath10k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
u32 *vdev_id = data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k *ar = arvif->ar;
struct ieee80211_hw *hw = ar->hw;
@@ -2077,7 +2083,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
u32 aid;
lockdep_assert_held(&ar->conf_mutex);
@@ -2153,7 +2159,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
@@ -2216,7 +2222,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
struct wmi_peer_assoc_complete_arg *arg)
{
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -2440,7 +2446,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
struct wmi_peer_assoc_complete_arg *arg)
{
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u16 *vht_mcs_mask;
@@ -2480,6 +2486,9 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
arg->peer_flags |= ar->wmi.peer_flags->bw80;
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
+ arg->peer_flags |= ar->wmi.peer_flags->bw160;
+
arg->peer_vht_rates.rx_max_rate =
__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
arg->peer_vht_rates.rx_mcs_set =
@@ -2498,7 +2507,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
@@ -2533,12 +2542,39 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
ATH10K_MAC_FIRST_OFDM_RATE_IDX;
}
+static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
+ struct ieee80211_sta *sta)
+{
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
+ switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
+ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
+ return MODE_11AC_VHT160;
+ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
+ return MODE_11AC_VHT80_80;
+ default:
+ /* not sure if this is a valid case? */
+ return MODE_11AC_VHT160;
+ }
+ }
+
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
+ return MODE_11AC_VHT80;
+
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
+ return MODE_11AC_VHT40;
+
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
+ return MODE_11AC_VHT20;
+
+ return MODE_UNKNOWN;
+}
+
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -2579,12 +2615,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
*/
if (sta->vht_cap.vht_supported &&
!ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
- if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
- phymode = MODE_11AC_VHT80;
- else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
- phymode = MODE_11AC_VHT40;
- else if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
- phymode = MODE_11AC_VHT20;
+ phymode = ath10k_mac_get_phymode_vht(ar, sta);
} else if (sta->ht_cap.ht_supported &&
!ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
@@ -2658,7 +2689,7 @@ static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta_vht_cap vht_cap)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret;
u32 param;
u32 value;
@@ -2725,7 +2756,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_sta_vht_cap vht_cap;
struct wmi_peer_assoc_complete_arg peer_arg;
@@ -2818,7 +2849,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ieee80211_sta_vht_cap vht_cap = {};
int ret;
@@ -2851,7 +2882,7 @@ static int ath10k_station_assoc(struct ath10k *ar,
struct ieee80211_sta *sta,
bool reassoc)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_peer_assoc_complete_arg peer_arg;
int ret = 0;
@@ -2918,7 +2949,7 @@ static int ath10k_station_disassoc(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
@@ -3144,7 +3175,7 @@ static void ath10k_mac_tx_unlock_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath10k *ar = data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (arvif->tx_paused)
return;
@@ -3231,7 +3262,7 @@ struct ath10k_mac_tx_pause {
static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_mac_tx_pause *arg = data;
if (arvif->vdev_id != arg->vdev_id)
@@ -3327,7 +3358,7 @@ static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
return false;
if (vif)
- return !ath10k_vif_to_arvif(vif)->nohwcrypt;
+ return !((struct ath10k_vif *)vif->drv_priv)->nohwcrypt;
return true;
}
@@ -3392,7 +3423,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
/* This is case only for P2P_GO */
if (vif->type != NL80211_IFTYPE_AP || !vif->p2p)
@@ -3774,6 +3805,9 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
if (!peer)
return NULL;
+ if (peer->removed)
+ return NULL;
+
if (peer->sta)
return peer->sta->txq[tid];
else if (peer->vif)
@@ -4311,6 +4345,13 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
vht_cap.cap |= val;
}
+ /* Currently the firmware seems to be buggy, don't enable 80+80
+ * mode until that's resolved.
+ */
+ if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
+ !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+ vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+
mcs_map = 0;
for (i = 0; i < 8; i++) {
if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
@@ -4808,7 +4849,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
enum wmi_sta_powersave_param param;
int ret = 0;
@@ -5144,7 +5185,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
int ret;
int i;
@@ -5279,7 +5320,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
u32 changed)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret = 0;
u32 vdev_param, pdev_param, slottime, preamble;
@@ -5471,7 +5512,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_scan_request *hw_req)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_scan_request *req = &hw_req->req;
struct wmi_start_scan_arg arg;
int ret = 0;
@@ -5603,7 +5644,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
const u8 *peer_addr;
bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
@@ -5742,7 +5783,7 @@ static void ath10k_set_default_unicast_key(struct ieee80211_hw *hw,
int keyidx)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret;
mutex_lock(&arvif->ar->conf_mutex);
@@ -5923,7 +5964,7 @@ static int ath10k_mac_tdls_vif_stations_count(struct ieee80211_hw *hw,
static void ath10k_mac_tdls_vifs_count_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int *num_tdls_vifs = data;
if (vif->type != NL80211_IFTYPE_STATION)
@@ -5951,7 +5992,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state new_state)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
struct ath10k_peer *peer;
int ret = 0;
@@ -6186,7 +6227,7 @@ exit:
static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
u16 ac, bool enable)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_sta_uapsd_auto_trig_arg arg = {};
u32 prio = 0, acc = 0;
u32 value = 0;
@@ -6294,7 +6335,7 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw,
const struct ieee80211_tx_queue_params *params)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_wmm_params_arg *p = NULL;
int ret;
@@ -6368,7 +6409,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
enum ieee80211_roc_type type)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_start_scan_arg arg;
int ret = 0;
u32 scan_time_msec;
@@ -6868,7 +6909,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
struct ath10k *ar = arvif->ar;
enum nl80211_band band;
@@ -6969,6 +7010,9 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
bw = WMI_PEER_CHWIDTH_80MHZ;
break;
case IEEE80211_STA_RX_BW_160:
+ bw = WMI_PEER_CHWIDTH_160MHZ;
+ break;
+ default:
ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
sta->bandwidth, sta->addr);
bw = WMI_PEER_CHWIDTH_20MHZ;
@@ -7016,7 +7060,7 @@ static void ath10k_offset_tsf(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, s64 tsf_offset)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
u32 offset, vdev_param;
int ret;
@@ -7041,7 +7085,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_ampdu_params *params)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ieee80211_sta *sta = params->sta;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
@@ -7139,7 +7183,7 @@ ath10k_mac_update_vif_chan(struct ath10k *ar,
ath10k_monitor_stop(ar);
for (i = 0; i < n_vifs; i++) {
- arvif = ath10k_vif_to_arvif(vifs[i].vif);
+ arvif = (void *)vifs[i].vif->drv_priv;
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
@@ -7172,7 +7216,7 @@ ath10k_mac_update_vif_chan(struct ath10k *ar,
spin_unlock_bh(&ar->data_lock);
for (i = 0; i < n_vifs; i++) {
- arvif = ath10k_vif_to_arvif(vifs[i].vif);
+ arvif = (void *)vifs[i].vif->drv_priv;
if (WARN_ON(!arvif->is_started))
continue;
@@ -7476,6 +7520,20 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
return 0;
}
+static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct ath10k *ar;
+ struct ath10k_peer *peer;
+
+ ar = hw->priv;
+
+ list_for_each_entry(peer, &ar->peers, list)
+ if (peer->sta == sta)
+ peer->removed = true;
+}
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_mac_op_tx,
.wake_tx_queue = ath10k_mac_op_wake_tx_queue,
@@ -7516,6 +7574,7 @@ static const struct ieee80211_ops ath10k_ops = {
.assign_vif_chanctx = ath10k_mac_op_assign_vif_chanctx,
.unassign_vif_chanctx = ath10k_mac_op_unassign_vif_chanctx,
.switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx,
+ .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
@@ -7814,7 +7873,7 @@ static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath10k_vif_iter *arvif_iter = data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (arvif->vdev_id == arvif_iter->vdev_id)
arvif_iter->arvif = arvif;