diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-03-31 17:29:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-03-31 17:29:33 -0700 |
commit | 29d9f30d4ce6c7a38745a54a8cddface10013490 (patch) | |
tree | 85649ba6a7b39203584d8db9365e03f64e62c136 /drivers/net/wireless/mediatek/mt76/mac80211.c | |
parent | 56a451b780676bc1cdac011735fe2869fa2e9abf (diff) | |
parent | 7f80ccfe996871ca69648efee74a60ae7ad0dcd9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from David Miller:
"Highlights:
1) Fix the iwlwifi regression, from Johannes Berg.
2) Support BSS coloring and 802.11 encapsulation offloading in
hardware, from John Crispin.
3) Fix some potential Spectre issues in qtnfmac, from Sergey
Matyukevich.
4) Add TTL decrement action to openvswitch, from Matteo Croce.
5) Allow paralleization through flow_action setup by not taking the
RTNL mutex, from Vlad Buslov.
6) A lot of zero-length array to flexible-array conversions, from
Gustavo A. R. Silva.
7) Align XDP statistics names across several drivers for consistency,
from Lorenzo Bianconi.
8) Add various pieces of infrastructure for offloading conntrack, and
make use of it in mlx5 driver, from Paul Blakey.
9) Allow using listening sockets in BPF sockmap, from Jakub Sitnicki.
10) Lots of parallelization improvements during configuration changes
in mlxsw driver, from Ido Schimmel.
11) Add support to devlink for generic packet traps, which report
packets dropped during ACL processing. And use them in mlxsw
driver. From Jiri Pirko.
12) Support bcmgenet on ACPI, from Jeremy Linton.
13) Make BPF compatible with RT, from Thomas Gleixnet, Alexei
Starovoitov, and your's truly.
14) Support XDP meta-data in virtio_net, from Yuya Kusakabe.
15) Fix sysfs permissions when network devices change namespaces, from
Christian Brauner.
16) Add a flags element to ethtool_ops so that drivers can more simply
indicate which coalescing parameters they actually support, and
therefore the generic layer can validate the user's ethtool
request. Use this in all drivers, from Jakub Kicinski.
17) Offload FIFO qdisc in mlxsw, from Petr Machata.
18) Support UDP sockets in sockmap, from Lorenz Bauer.
19) Fix stretch ACK bugs in several TCP congestion control modules,
from Pengcheng Yang.
20) Support virtual functiosn in octeontx2 driver, from Tomasz
Duszynski.
21) Add region operations for devlink and use it in ice driver to dump
NVM contents, from Jacob Keller.
22) Add support for hw offload of MACSEC, from Antoine Tenart.
23) Add support for BPF programs that can be attached to LSM hooks,
from KP Singh.
24) Support for multiple paths, path managers, and counters in MPTCP.
From Peter Krystad, Paolo Abeni, Florian Westphal, Davide Caratti,
and others.
25) More progress on adding the netlink interface to ethtool, from
Michal Kubecek"
* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2121 commits)
net: ipv6: rpl_iptunnel: Fix potential memory leak in rpl_do_srh_inline
cxgb4/chcr: nic-tls stats in ethtool
net: dsa: fix oops while probing Marvell DSA switches
net/bpfilter: remove superfluous testing message
net: macb: Fix handling of fixed-link node
net: dsa: ksz: Select KSZ protocol tag
netdevsim: dev: Fix memory leak in nsim_dev_take_snapshot_write
net: stmmac: add EHL 2.5Gbps PCI info and PCI ID
net: stmmac: add EHL PSE0 & PSE1 1Gbps PCI info and PCI ID
net: stmmac: create dwmac-intel.c to contain all Intel platform
net: dsa: bcm_sf2: Support specifying VLAN tag egress rule
net: dsa: bcm_sf2: Add support for matching VLAN TCI
net: dsa: bcm_sf2: Move writing of CFP_DATA(5) into slicing functions
net: dsa: bcm_sf2: Check earlier for FLOW_EXT and FLOW_MAC_EXT
net: dsa: bcm_sf2: Disable learning for ASP port
net: dsa: b53: Deny enslaving port 7 for 7278 into a bridge
net: dsa: b53: Prevent tagged VLAN on port 7 for 7278
net: dsa: b53: Restore VLAN entries upon (re)configuration
net: dsa: bcm_sf2: Fix overflow checks
hv_netvsc: Remove unnecessary round_up for recv_completion_cnt
...
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mac80211.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mac80211.c | 392 |
1 files changed, 263 insertions, 129 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 96018fd65779..f44f99184c10 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -121,7 +121,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, bool vht) { struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; - int i, nstream = hweight8(dev->antenna_mask); + int i, nstream = hweight8(dev->phy.antenna_mask); struct ieee80211_sta_vht_cap *vht_cap; u16 mcs_map = 0; @@ -156,9 +156,9 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, void mt76_set_stream_caps(struct mt76_dev *dev, bool vht) { if (dev->cap.has_2ghz) - mt76_init_stream_cap(dev, &dev->sband_2g.sband, false); + mt76_init_stream_cap(dev, &dev->phy.sband_2g.sband, false); if (dev->cap.has_5ghz) - mt76_init_stream_cap(dev, &dev->sband_5g.sband, vht); + mt76_init_stream_cap(dev, &dev->phy.sband_5g.sband, vht); } EXPORT_SYMBOL_GPL(mt76_set_stream_caps); @@ -187,8 +187,6 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, sband->n_channels = n_chan; sband->bitrates = rates; sband->n_bitrates = n_rates; - dev->chandef.chan = &sband->channels[0]; - dev->chan_state = &msband->chan[0]; ht_cap = &sband->ht_cap; ht_cap->ht_supported = true; @@ -223,9 +221,9 @@ static int mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates, int n_rates) { - dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->sband_2g.sband; + dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->phy.sband_2g.sband; - return mt76_init_sband(dev, &dev->sband_2g, + return mt76_init_sband(dev, &dev->phy.sband_2g, mt76_channels_2ghz, ARRAY_SIZE(mt76_channels_2ghz), rates, n_rates, false); @@ -235,18 +233,19 @@ static int mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, int n_rates, bool vht) { - dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->sband_5g.sband; + dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->phy.sband_5g.sband; - return mt76_init_sband(dev, &dev->sband_5g, + return mt76_init_sband(dev, &dev->phy.sband_5g, mt76_channels_5ghz, ARRAY_SIZE(mt76_channels_5ghz), rates, n_rates, vht); } static void -mt76_check_sband(struct mt76_dev *dev, int band) +mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, + enum nl80211_band band) { - struct ieee80211_supported_band *sband = dev->hw->wiphy->bands[band]; + struct ieee80211_supported_band *sband = &msband->sband; bool found = false; int i; @@ -261,20 +260,145 @@ mt76_check_sband(struct mt76_dev *dev, int band) break; } - if (found) + if (found) { + phy->chandef.chan = &sband->channels[0]; + phy->chan_state = &msband->chan[0]; return; + } sband->n_channels = 0; - dev->hw->wiphy->bands[band] = NULL; + phy->hw->wiphy->bands[band] = NULL; } +static void +mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) +{ + struct wiphy *wiphy = hw->wiphy; + + SET_IEEE80211_DEV(hw, dev->dev); + SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); + + wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); + + wiphy->available_antennas_tx = dev->phy.antenna_mask; + wiphy->available_antennas_rx = dev->phy.antenna_mask; + + hw->txq_data_size = sizeof(struct mt76_txq); + + if (!hw->max_tx_fragments) + hw->max_tx_fragments = 16; + + ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, PS_NULLFUNC_STACK); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); + ieee80211_hw_set(hw, TX_AMSDU); + ieee80211_hw_set(hw, TX_FRAG_LIST); + ieee80211_hw_set(hw, MFP_CAPABLE); + ieee80211_hw_set(hw, AP_LINK_PS); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); + + wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_ADHOC); +} + +struct mt76_phy * +mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, + const struct ieee80211_ops *ops) +{ + struct ieee80211_hw *hw; + struct mt76_phy *phy; + unsigned int phy_size, chan_size; + unsigned int size_2g, size_5g; + void *priv; + + phy_size = ALIGN(sizeof(*phy), 8); + chan_size = sizeof(dev->phy.sband_2g.chan[0]); + size_2g = ALIGN(ARRAY_SIZE(mt76_channels_2ghz) * chan_size, 8); + size_5g = ALIGN(ARRAY_SIZE(mt76_channels_5ghz) * chan_size, 8); + + size += phy_size + size_2g + size_5g; + hw = ieee80211_alloc_hw(size, ops); + if (!hw) + return NULL; + + phy = hw->priv; + phy->dev = dev; + phy->hw = hw; + + mt76_phy_init(dev, hw); + + priv = hw->priv + phy_size; + + phy->sband_2g = dev->phy.sband_2g; + phy->sband_2g.chan = priv; + priv += size_2g; + + phy->sband_5g = dev->phy.sband_5g; + phy->sband_5g.chan = priv; + priv += size_5g; + + phy->priv = priv; + + hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; + hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; + + mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); + mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); + + return phy; +} +EXPORT_SYMBOL_GPL(mt76_alloc_phy); + +int +mt76_register_phy(struct mt76_phy *phy) +{ + int ret; + + ret = ieee80211_register_hw(phy->hw); + if (ret) + return ret; + + phy->dev->phy2 = phy; + return 0; +} +EXPORT_SYMBOL_GPL(mt76_register_phy); + +void +mt76_unregister_phy(struct mt76_phy *phy) +{ + struct mt76_dev *dev = phy->dev; + + dev->phy2 = NULL; + mt76_tx_status_check(dev, NULL, true); + ieee80211_unregister_hw(phy->hw); +} +EXPORT_SYMBOL_GPL(mt76_unregister_phy); + struct mt76_dev * mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, const struct mt76_driver_ops *drv_ops) { struct ieee80211_hw *hw; + struct mt76_phy *phy; struct mt76_dev *dev; + int i; hw = ieee80211_alloc_hw(size, ops); if (!hw) @@ -285,6 +409,10 @@ mt76_alloc_device(struct device *pdev, unsigned int size, dev->dev = pdev; dev->drv = drv_ops; + phy = &dev->phy; + phy->dev = dev; + phy->hw = hw; + spin_lock_init(&dev->rx_lock); spin_lock_init(&dev->lock); spin_lock_init(&dev->cc_lock); @@ -292,6 +420,15 @@ mt76_alloc_device(struct device *pdev, unsigned int size, init_waitqueue_head(&dev->tx_wait); skb_queue_head_init(&dev->status_list); + skb_queue_head_init(&dev->mcu.res_q); + init_waitqueue_head(&dev->mcu.wait); + mutex_init(&dev->mcu.mutex); + + INIT_LIST_HEAD(&dev->txwi_cache); + + for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) + skb_queue_head_init(&dev->rx_skb[i]); + tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev); return dev; @@ -302,51 +439,11 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates) { struct ieee80211_hw *hw = dev->hw; - struct wiphy *wiphy = hw->wiphy; + struct mt76_phy *phy = &dev->phy; int ret; dev_set_drvdata(dev->dev, dev); - - INIT_LIST_HEAD(&dev->txwi_cache); - - SET_IEEE80211_DEV(hw, dev->dev); - SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); - - wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; - - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); - - wiphy->available_antennas_tx = dev->antenna_mask; - wiphy->available_antennas_rx = dev->antenna_mask; - - hw->txq_data_size = sizeof(struct mt76_txq); - hw->max_tx_fragments = 16; - - ieee80211_hw_set(hw, SIGNAL_DBM); - ieee80211_hw_set(hw, PS_NULLFUNC_STACK); - ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); - ieee80211_hw_set(hw, AMPDU_AGGREGATION); - ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); - ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); - ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); - ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); - ieee80211_hw_set(hw, TX_AMSDU); - ieee80211_hw_set(hw, TX_FRAG_LIST); - ieee80211_hw_set(hw, MFP_CAPABLE); - ieee80211_hw_set(hw, AP_LINK_PS); - ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); - ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); - - wiphy->flags |= WIPHY_FLAG_IBSS_RSN; - wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_ADHOC); + mt76_phy_init(dev, hw); if (dev->cap.has_2ghz) { ret = mt76_init_sband_2g(dev, rates, n_rates); @@ -360,9 +457,9 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, return ret; } - wiphy_read_of_freq_limits(dev->hw->wiphy); - mt76_check_sband(dev, NL80211_BAND_2GHZ); - mt76_check_sband(dev, NL80211_BAND_5GHZ); + wiphy_read_of_freq_limits(hw->wiphy); + mt76_check_sband(&dev->phy, &phy->sband_2g, NL80211_BAND_2GHZ); + mt76_check_sband(&dev->phy, &phy->sband_5g, NL80211_BAND_5GHZ); if (IS_ENABLED(CONFIG_MT76_LEDS)) { ret = mt76_led_init(dev); @@ -394,7 +491,10 @@ EXPORT_SYMBOL_GPL(mt76_free_device); void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) { - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) { + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy); + + if (!test_bit(MT76_STATE_RUNNING, &phy->state)) { dev_kfree_skb(skb); return; } @@ -403,13 +503,16 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(mt76_rx); -bool mt76_has_tx_pending(struct mt76_dev *dev) +bool mt76_has_tx_pending(struct mt76_phy *phy) { + struct mt76_dev *dev = phy->dev; struct mt76_queue *q; - int i; + int i, offset; - for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { - q = dev->q_tx[i].q; + offset = __MT_TXQ_MAX * (phy != &dev->phy); + + for (i = 0; i < __MT_TXQ_MAX; i++) { + q = dev->q_tx[offset + i].q; if (q && q->queued) return true; } @@ -419,37 +522,45 @@ bool mt76_has_tx_pending(struct mt76_dev *dev) EXPORT_SYMBOL_GPL(mt76_has_tx_pending); static struct mt76_channel_state * -mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c) +mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c) { struct mt76_sband *msband; int idx; if (c->band == NL80211_BAND_2GHZ) - msband = &dev->sband_2g; + msband = &phy->sband_2g; else - msband = &dev->sband_5g; + msband = &phy->sband_5g; idx = c - &msband->sband.channels[0]; return &msband->chan[idx]; } +static void +mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time) +{ + struct mt76_channel_state *state = phy->chan_state; + + state->cc_active += ktime_to_us(ktime_sub(time, + phy->survey_time)); + phy->survey_time = time; +} + void mt76_update_survey(struct mt76_dev *dev) { - struct mt76_channel_state *state = dev->chan_state; ktime_t cur_time; - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) - return; - if (dev->drv->update_survey) dev->drv->update_survey(dev); cur_time = ktime_get_boottime(); - state->cc_active += ktime_to_us(ktime_sub(cur_time, - dev->survey_time)); - dev->survey_time = cur_time; + mt76_update_survey_active_time(&dev->phy, cur_time); + if (dev->phy2) + mt76_update_survey_active_time(dev->phy2, cur_time); if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) { + struct mt76_channel_state *state = dev->phy.chan_state; + spin_lock_bh(&dev->cc_lock); state->cc_bss_rx += dev->cur_cc_bss_rx; dev->cur_cc_bss_rx = 0; @@ -458,31 +569,33 @@ void mt76_update_survey(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_update_survey); -void mt76_set_channel(struct mt76_dev *dev) +void mt76_set_channel(struct mt76_phy *phy) { - struct ieee80211_hw *hw = dev->hw; + struct mt76_dev *dev = phy->dev; + struct ieee80211_hw *hw = phy->hw; struct cfg80211_chan_def *chandef = &hw->conf.chandef; bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; int timeout = HZ / 5; - wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), timeout); + wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); mt76_update_survey(dev); - dev->chandef = *chandef; - dev->chan_state = mt76_channel_state(dev, chandef->chan); + phy->chandef = *chandef; + phy->chan_state = mt76_channel_state(phy, chandef->chan); if (!offchannel) - dev->main_chan = chandef->chan; + phy->main_chan = chandef->chan; - if (chandef->chan != dev->main_chan) - memset(dev->chan_state, 0, sizeof(*dev->chan_state)); + if (chandef->chan != phy->main_chan) + memset(phy->chan_state, 0, sizeof(*phy->chan_state)); } EXPORT_SYMBOL_GPL(mt76_set_channel); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; struct mt76_sband *sband; struct ieee80211_channel *chan; struct mt76_channel_state *state; @@ -492,10 +605,10 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, if (idx == 0 && dev->drv->update_survey) mt76_update_survey(dev); - sband = &dev->sband_2g; + sband = &phy->sband_2g; if (idx >= sband->sband.n_channels) { idx -= sband->sband.n_channels; - sband = &dev->sband_5g; + sband = &phy->sband_5g; } if (idx >= sband->sband.n_channels) { @@ -504,13 +617,16 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, } chan = &sband->sband.channels[idx]; - state = mt76_channel_state(dev, chan); + state = mt76_channel_state(phy, chan); memset(survey, 0, sizeof(*survey)); survey->channel = chan; survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; survey->filled |= dev->drv->survey_flags; - if (chan == dev->main_chan) { + if (state->noise) + survey->filled |= SURVEY_INFO_NOISE_DBM; + + if (chan == phy->main_chan) { survey->filled |= SURVEY_INFO_IN_USE; if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) @@ -520,6 +636,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, survey->time_busy = div_u64(state->cc_busy, 1000); survey->time_rx = div_u64(state->cc_rx, 1000); survey->time = div_u64(state->cc_active, 1000); + survey->noise = state->noise; spin_lock_bh(&dev->cc_lock); survey->time_bss_rx = div_u64(state->cc_bss_rx, 1000); @@ -555,8 +672,12 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid, } EXPORT_SYMBOL(mt76_wcid_key_setup); -static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb) +static void +mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, + struct ieee80211_hw **hw, + struct ieee80211_sta **sta) { + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct mt76_rx_status mstat; @@ -581,7 +702,8 @@ static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb) memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal)); - return wcid_to_sta(mstat.wcid); + *sta = wcid_to_sta(mstat.wcid); + *hw = mt76_phy_hw(dev, mstat.ext_phy); } static int @@ -628,10 +750,18 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, int len) { struct mt76_wcid *wcid = status->wcid; + struct ieee80211_rx_status info = { + .enc_flags = status->enc_flags, + .rate_idx = status->rate_idx, + .encoding = status->encoding, + .band = status->band, + .nss = status->nss, + .bw = status->bw, + }; struct ieee80211_sta *sta; u32 airtime; - airtime = mt76_calc_rx_airtime(dev, status, len); + airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len); spin_lock(&dev->cc_lock); dev->cur_cc_bss_rx += airtime; spin_unlock(&dev->cc_lock); @@ -707,12 +837,14 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_sta *sta; + struct ieee80211_hw *hw; struct mt76_wcid *wcid = status->wcid; bool ps; int i; + hw = mt76_phy_hw(dev, status->ext_phy); if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { - sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL); + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); if (sta) wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv; } @@ -770,7 +902,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; if (!skb_queue_empty(&mtxq->retry_q)) - ieee80211_schedule_txq(dev->hw, sta->txq[i]); + ieee80211_schedule_txq(hw, sta->txq[i]); } } @@ -778,6 +910,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, struct napi_struct *napi) { struct ieee80211_sta *sta; + struct ieee80211_hw *hw; struct sk_buff *skb; spin_lock(&dev->rx_lock); @@ -787,8 +920,8 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, continue; } - sta = mt76_rx_convert(skb); - ieee80211_rx_napi(dev->hw, sta, skb, napi); + mt76_rx_convert(dev, skb, &hw, &sta); + ieee80211_rx_napi(hw, sta, skb, napi); } spin_unlock(&dev->rx_lock); } @@ -812,7 +945,7 @@ EXPORT_SYMBOL_GPL(mt76_rx_poll_complete); static int mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, bool ext_phy) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int ret; @@ -837,6 +970,9 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, } ewma_signal_init(&wcid->rssi); + if (ext_phy) + mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); + wcid->ext_phy = ext_phy; rcu_assign_pointer(dev->wcid[wcid->idx], wcid); out: @@ -851,9 +987,6 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int i, idx = wcid->idx; - rcu_assign_pointer(dev->wcid[idx], NULL); - synchronize_rcu(); - for (i = 0; i < ARRAY_SIZE(wcid->aggr); i++) mt76_rx_aggr_stop(dev, wcid, i); @@ -863,7 +996,8 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, mt76_tx_status_check(dev, wcid, true); for (i = 0; i < ARRAY_SIZE(sta->txq); i++) mt76_txq_remove(dev, sta->txq[i]); - mt76_wcid_free(dev->wcid_mask, idx); + mt76_wcid_mask_clear(dev->wcid_mask, idx); + mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); } EXPORT_SYMBOL_GPL(__mt76_sta_remove); @@ -881,11 +1015,13 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) - return mt76_sta_add(dev, vif, sta); + return mt76_sta_add(dev, vif, sta, ext_phy); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && @@ -900,30 +1036,27 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_sta_state); +void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + + mutex_lock(&dev->mutex); + rcu_assign_pointer(dev->wcid[wcid->idx], NULL); + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); + int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { - struct mt76_dev *dev = hw->priv; - int n_chains = hweight8(dev->antenna_mask); + struct mt76_phy *phy = hw->priv; + int n_chains = hweight8(phy->antenna_mask); + int delta = mt76_tx_power_nss_delta(n_chains); - *dbm = DIV_ROUND_UP(dev->txpower_cur, 2); - - /* convert from per-chain power to combined - * output power - */ - switch (n_chains) { - case 4: - *dbm += 6; - break; - case 3: - *dbm += 4; - break; - case 2: - *dbm += 3; - break; - default: - break; - } + *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2); return 0; } @@ -1005,11 +1138,11 @@ int mt76_get_rate(struct mt76_dev *dev, int i, offset = 0, len = sband->n_bitrates; if (cck) { - if (sband == &dev->sband_5g.sband) + if (sband == &dev->phy.sband_5g.sband) return 0; idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->sband_2g.sband) { + } else if (sband == &dev->phy.sband_2g.sband) { offset = 4; } @@ -1025,27 +1158,28 @@ EXPORT_SYMBOL_GPL(mt76_get_rate); void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; - set_bit(MT76_SCANNING, &dev->state); + set_bit(MT76_SCANNING, &phy->state); } EXPORT_SYMBOL_GPL(mt76_sw_scan); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; - clear_bit(MT76_SCANNING, &dev->state); + clear_bit(MT76_SCANNING, &phy->state); } EXPORT_SYMBOL_GPL(mt76_sw_scan_complete); int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; mutex_lock(&dev->mutex); - *tx_ant = dev->antenna_mask; - *rx_ant = dev->antenna_mask; + *tx_ant = phy->antenna_mask; + *rx_ant = phy->antenna_mask; mutex_unlock(&dev->mutex); return 0; |