mt76 patches for 5.8

* fixes for sparse warnings
 * DBDC fixes
 * mt7663 remain-on-channel support
 * mt7915 spatial reuse support
 * mt7915 radiotap fix
 * station wcid allocation fix
 * mt7663 powersave fix
 * mt7663 scan fix
 * mt7611n support
 * cleanup
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iEYEABECAAYFAl7P4I0ACgkQ130UHQKnbvUo6ACeMMZcRYKeggGafRG8Sg56pR26
 T8IAn0sXBHshLir4f4WsGBhLlrN6tbjy
 =cmhD
 -----END PGP SIGNATURE-----

Merge tag 'mt76-for-kvalo-2020-05-28' of https://github.com/nbd168/wireless

mt76 patches for 5.8

* fixes for sparse warnings
* DBDC fixes
* mt7663 remain-on-channel support
* mt7915 spatial reuse support
* mt7915 radiotap fix
* station wcid allocation fix
* mt7663 powersave fix
* mt7663 scan fix
* mt7611n support
* cleanup

# gpg: Signature made Thu 28 May 2020 07:02:21 PM EEST using DSA key ID 02A76EF5
# gpg: Good signature from "Felix Fietkau <nbd@nbd.name>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 75D1 1A7D 91A7 710F 4900  42EF D77D 141D 02A7 6EF5
This commit is contained in:
Kalle Valo 2020-05-29 20:42:30 +03:00
commit 5cf2740f1d
27 changed files with 335 additions and 124 deletions

View File

@ -51,7 +51,7 @@ static int mt76_rx_queues_read(struct seq_file *s, void *data)
struct mt76_dev *dev = dev_get_drvdata(s->private); struct mt76_dev *dev = dev_get_drvdata(s->private);
int i, queued; int i, queued;
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { mt76_for_each_q_rx(dev, i) {
struct mt76_queue *q = &dev->q_rx[i]; struct mt76_queue *q = &dev->q_rx[i];
if (!q->ndesc) if (!q->ndesc)

View File

@ -576,7 +576,7 @@ mt76_dma_init(struct mt76_dev *dev)
init_dummy_netdev(&dev->napi_dev); init_dummy_netdev(&dev->napi_dev);
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { mt76_for_each_q_rx(dev, i) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
64); 64);
mt76_dma_rx_fill(dev, &dev->q_rx[i]); mt76_dma_rx_fill(dev, &dev->q_rx[i]);
@ -610,7 +610,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++)
mt76_dma_tx_cleanup(dev, i, true); mt76_dma_tx_cleanup(dev, i, true);
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { mt76_for_each_q_rx(dev, i) {
netif_napi_del(&dev->napi[i]); netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, &dev->q_rx[i]); mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
} }

View File

@ -288,8 +288,8 @@ enum {
MT76_REMOVED, MT76_REMOVED,
MT76_READING_STATS, MT76_READING_STATS,
MT76_STATE_POWER_OFF, MT76_STATE_POWER_OFF,
MT76_STATE_PS,
MT76_STATE_SUSPEND, MT76_STATE_SUSPEND,
MT76_STATE_ROC,
}; };
struct mt76_hw_cap { struct mt76_hw_cap {
@ -537,8 +537,8 @@ struct mt76_dev {
wait_queue_head_t tx_wait; wait_queue_head_t tx_wait;
struct sk_buff_head status_list; struct sk_buff_head status_list;
unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG]; u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
unsigned long wcid_phy_mask[MT76_N_WCIDS / BITS_PER_LONG]; u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
struct mt76_wcid global_wcid; struct mt76_wcid global_wcid;
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
@ -671,6 +671,10 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
#define mt76_for_each_q_rx(dev, i) \
for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \
(dev)->q_rx[i].ndesc; i++)
struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops, const struct ieee80211_ops *ops,
const struct mt76_driver_ops *drv_ops); const struct mt76_driver_ops *drv_ops);

View File

@ -473,7 +473,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast)
struct mt7603_sta *sta; struct mt7603_sta *sta;
struct mt76_wcid *wcid; struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->mt76.wcid)) if (idx >= MT7603_WTBL_SIZE)
return NULL; return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]); wcid = rcu_dereference(dev->mt76.wcid[idx]);
@ -1238,7 +1238,7 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
if (pid == MT_PACKET_ID_NO_ACK) if (pid == MT_PACKET_ID_NO_ACK)
return; return;
if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) if (wcidx >= MT7603_WTBL_SIZE)
return; return;
rcu_read_lock(); rcu_read_lock();
@ -1438,8 +1438,9 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++) for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true); mt76_queue_tx_cleanup(dev, i, true);
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i); mt76_queue_rx_reset(dev, i);
}
mt7603_dma_sched_reset(dev); mt7603_dma_sched_reset(dev);

View File

@ -111,6 +111,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
return; return;
} }
if (is_mt7611(&dev->mt76)) {
/* 5GHz only */
dev->mt76.cap.has_5ghz = true;
return;
}
val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
eeprom[MT_EE_WIFI_CONF]); eeprom[MT_EE_WIFI_CONF]);
switch (val) { switch (val) {
@ -310,6 +316,7 @@ static void mt7615_cal_free_data(struct mt7615_dev *dev)
mt7622_apply_cal_free_data(dev); mt7622_apply_cal_free_data(dev);
break; break;
case 0x7615: case 0x7615:
case 0x7611:
mt7615_apply_cal_free_data(dev); mt7615_apply_cal_free_data(dev);
break; break;
} }

View File

@ -139,8 +139,10 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
wiphy->max_remain_on_channel_duration = 5000;
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
NL80211_FEATURE_P2P_GO_CTWIN | NL80211_FEATURE_P2P_GO_CTWIN |
NL80211_FEATURE_P2P_GO_OPPPS; NL80211_FEATURE_P2P_GO_OPPPS;
} else { } else {
@ -149,6 +151,8 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
dev->ops->sched_scan_start = NULL; dev->ops->sched_scan_start = NULL;
dev->ops->sched_scan_stop = NULL; dev->ops->sched_scan_stop = NULL;
dev->ops->set_rekey_data = NULL; dev->ops->set_rekey_data = NULL;
dev->ops->remain_on_channel = NULL;
dev->ops->cancel_remain_on_channel = NULL;
wiphy->max_sched_scan_plan_interval = 0; wiphy->max_sched_scan_plan_interval = 0;
wiphy->max_sched_scan_ie_len = 0; wiphy->max_sched_scan_ie_len = 0;
@ -368,12 +372,6 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
if (phy) if (phy)
return 0; return 0;
INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work);
skb_queue_head_init(&phy->scan_event_list);
INIT_WORK(&phy->ps_work, mt7615_ps_work);
mt7615_cap_dbdc_enable(dev); mt7615_cap_dbdc_enable(dev);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops);
if (!mphy) if (!mphy)
@ -386,6 +384,14 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mt7615_init_wiphy(mphy->hw); mt7615_init_wiphy(mphy->hw);
INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work);
skb_queue_head_init(&phy->scan_event_list);
INIT_WORK(&phy->roc_work, mt7615_roc_work);
timer_setup(&phy->roc_timer, mt7615_roc_timer, 0);
init_waitqueue_head(&phy->roc_wait);
mt7615_mac_set_scs(phy, true); mt7615_mac_set_scs(phy, true);
/* /*
@ -437,9 +443,11 @@ void mt7615_init_device(struct mt7615_dev *dev)
INIT_LIST_HEAD(&dev->sta_poll_list); INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock); spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait); init_waitqueue_head(&dev->reset_wait);
init_waitqueue_head(&dev->phy.roc_wait);
INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
INIT_WORK(&dev->phy.ps_work, mt7615_ps_work); INIT_WORK(&dev->phy.roc_work, mt7615_roc_work);
timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0);
mt7615_init_wiphy(hw); mt7615_init_wiphy(hw);
dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;

View File

@ -61,7 +61,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
struct mt7615_sta *sta; struct mt7615_sta *sta;
struct mt76_wcid *wcid; struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->mt76.wcid)) if (idx >= MT7615_WTBL_SIZE)
return NULL; return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]); wcid = rcu_dereference(dev->mt76.wcid[idx]);
@ -175,7 +175,8 @@ mt7615_get_status_freq_info(struct mt7615_dev *dev, struct mt76_phy *mphy,
struct mt76_rx_status *status, u8 chfreq) struct mt76_rx_status *status, u8 chfreq)
{ {
if (!test_bit(MT76_HW_SCANNING, &mphy->state) && if (!test_bit(MT76_HW_SCANNING, &mphy->state) &&
!test_bit(MT76_HW_SCHED_SCANNING, &mphy->state)) { !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) &&
!test_bit(MT76_STATE_ROC, &mphy->state)) {
status->freq = mphy->chandef.chan->center_freq; status->freq = mphy->chandef.chan->center_freq;
status->band = mphy->chandef.chan->band; status->band = mphy->chandef.chan->band;
return; return;
@ -1302,7 +1303,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
if (pid == MT_PACKET_ID_NO_ACK) if (pid == MT_PACKET_ID_NO_ACK)
return; return;
if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) if (wcidx >= MT7615_WTBL_SIZE)
return; return;
rcu_read_lock(); rcu_read_lock();
@ -1819,8 +1820,9 @@ void mt7615_dma_reset(struct mt7615_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++) for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true); mt76_queue_tx_cleanup(dev, i, true);
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i); mt76_queue_rx_reset(dev, i);
}
mt76_set(dev, MT_WPDMA_GLO_CFG, mt76_set(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
@ -1849,8 +1851,13 @@ void mt7615_mac_reset_work(struct work_struct *work)
set_bit(MT76_MCU_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait); wake_up(&dev->mt76.mcu.wait);
cancel_delayed_work_sync(&dev->phy.mac_work); cancel_delayed_work_sync(&dev->phy.mac_work);
if (phy2) del_timer_sync(&dev->phy.roc_timer);
cancel_work_sync(&dev->phy.roc_work);
if (phy2) {
cancel_delayed_work_sync(&phy2->mac_work); cancel_delayed_work_sync(&phy2->mac_work);
del_timer_sync(&phy2->roc_timer);
cancel_work_sync(&phy2->roc_work);
}
/* lock/unlock all queues to ensure that no tx is pending */ /* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy); mt76_txq_schedule_all(&dev->mphy);

View File

@ -71,7 +71,8 @@ static void mt7615_stop(struct ieee80211_hw *hw)
struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw);
cancel_delayed_work_sync(&phy->mac_work); cancel_delayed_work_sync(&phy->mac_work);
cancel_work_sync(&phy->ps_work); del_timer_sync(&phy->roc_timer);
cancel_work_sync(&phy->roc_work);
mutex_lock(&dev->mt76.mutex); mutex_lock(&dev->mt76.mutex);
@ -289,12 +290,11 @@ mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd,
wd->type = MT7615_WTBL_KEY_DESC; wd->type = MT7615_WTBL_KEY_DESC;
wd->sta = msta; wd->sta = msta;
wd->key.key = kzalloc(key->keylen, GFP_KERNEL); wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL);
if (!wd->key.key) { if (!wd->key.key) {
kfree(wd); kfree(wd);
return -ENOMEM; return -ENOMEM;
} }
memcpy(wd->key.key, key->key, key->keylen);
wd->key.cipher = key->cipher; wd->key.cipher = key->cipher;
wd->key.keyidx = key->keyidx; wd->key.keyidx = key->keyidx;
wd->key.keylen = key->keylen; wd->key.keylen = key->keylen;
@ -360,20 +360,6 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); return mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
} }
void mt7615_ps_work(struct work_struct *work)
{
struct mt7615_phy *phy;
phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy,
ps_work);
mutex_lock(&phy->dev->mt76.mutex);
ieee80211_iterate_active_interfaces(phy->mt76->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
m7615_mcu_set_ps_iter, phy);
mutex_unlock(&phy->dev->mt76.mutex);
}
static int mt7615_config(struct ieee80211_hw *hw, u32 changed) static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
{ {
struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_dev *dev = mt7615_hw_dev(hw);
@ -399,14 +385,6 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
} }
if (changed & IEEE80211_CONF_CHANGE_PS) {
if (hw->conf.flags & IEEE80211_CONF_PS)
set_bit(MT76_STATE_PS, &phy->mt76->state);
else
clear_bit(MT76_STATE_PS, &phy->mt76->state);
ieee80211_queue_work(hw, &phy->ps_work);
}
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);
return ret; return ret;
@ -509,6 +487,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
BSS_CHANGED_BEACON_ENABLED)) BSS_CHANGED_BEACON_ENABLED))
mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
if (changed & BSS_CHANGED_PS)
mt7615_mcu_set_vif_ps(dev, vif);
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);
} }
@ -791,6 +772,37 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
return 0; return 0;
} }
static void mt7615_roc_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif)
{
struct mt7615_phy *phy = priv;
mt7615_mcu_set_roc(phy, vif, NULL, 0);
}
void mt7615_roc_work(struct work_struct *work)
{
struct mt7615_phy *phy;
phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy,
roc_work);
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
return;
ieee80211_iterate_active_interfaces(phy->mt76->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_roc_iter, phy);
ieee80211_remain_on_channel_expired(phy->mt76->hw);
}
void mt7615_roc_timer(struct timer_list *timer)
{
struct mt7615_phy *phy = from_timer(phy, timer, roc_timer);
ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
}
void mt7615_scan_work(struct work_struct *work) void mt7615_scan_work(struct work_struct *work)
{ {
struct mt7615_phy *phy; struct mt7615_phy *phy;
@ -864,6 +876,50 @@ mt7615_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return mt7615_mcu_sched_scan_enable(mphy->priv, vif, false); return mt7615_mcu_sched_scan_enable(mphy->priv, vif, false);
} }
static int mt7615_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
int duration,
enum ieee80211_roc_type type)
{
struct mt7615_phy *phy = mt7615_hw_phy(hw);
int err;
if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))
return 0;
err = mt7615_mcu_set_roc(phy, vif, chan, duration);
if (err < 0) {
clear_bit(MT76_STATE_ROC, &phy->mt76->state);
return err;
}
if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) {
mt7615_mcu_set_roc(phy, vif, NULL, 0);
clear_bit(MT76_STATE_ROC, &phy->mt76->state);
return -ETIMEDOUT;
}
return 0;
}
static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt7615_phy *phy = mt7615_hw_phy(hw);
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
return 0;
del_timer_sync(&phy->roc_timer);
cancel_work_sync(&phy->roc_work);
mt7615_mcu_set_roc(phy, vif, NULL, 0);
return 0;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int mt7615_suspend(struct ieee80211_hw *hw, static int mt7615_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan) struct cfg80211_wowlan *wowlan)
@ -978,6 +1034,8 @@ const struct ieee80211_ops mt7615_ops = {
.cancel_hw_scan = mt7615_cancel_hw_scan, .cancel_hw_scan = mt7615_cancel_hw_scan,
.sched_scan_start = mt7615_start_sched_scan, .sched_scan_start = mt7615_start_sched_scan,
.sched_scan_stop = mt7615_stop_sched_scan, .sched_scan_stop = mt7615_stop_sched_scan,
.remain_on_channel = mt7615_remain_on_channel,
.cancel_remain_on_channel = mt7615_cancel_remain_on_channel,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = mt7615_suspend, .suspend = mt7615_suspend,
.resume = mt7615_resume, .resume = mt7615_resume,

View File

@ -359,6 +359,33 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)
MT7615_HW_SCAN_TIMEOUT); MT7615_HW_SCAN_TIMEOUT);
} }
static void
mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)
{
struct mt7615_roc_tlv *event;
struct mt7615_phy *phy;
struct mt76_phy *mphy;
int duration;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt7615_roc_tlv *)skb->data;
if (event->dbdc_band && dev->mt76.phy2)
mphy = dev->mt76.phy2;
else
mphy = &dev->mt76.phy;
ieee80211_ready_on_channel(mphy->hw);
phy = (struct mt7615_phy *)mphy->priv;
phy->roc_grant = true;
wake_up(&phy->roc_wait);
duration = le32_to_cpu(event->max_interval);
mod_timer(&phy->roc_timer,
round_jiffies_up(jiffies + msecs_to_jiffies(duration)));
}
static void static void
mt7615_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) mt7615_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{ {
@ -426,6 +453,9 @@ mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)
case MCU_EVENT_BSS_BEACON_LOSS: case MCU_EVENT_BSS_BEACON_LOSS:
mt7615_mcu_beacon_loss_event(dev, skb); mt7615_mcu_beacon_loss_event(dev, skb);
break; break;
case MCU_EVENT_ROC:
mt7615_mcu_roc_event(dev, skb);
break;
case MCU_EVENT_SCHED_SCAN_DONE: case MCU_EVENT_SCHED_SCAN_DONE:
case MCU_EVENT_SCAN_DONE: case MCU_EVENT_SCAN_DONE:
mt7615_mcu_scan_event(dev, skb); mt7615_mcu_scan_event(dev, skb);
@ -451,6 +481,7 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb)
rxd->eid == MCU_EVENT_SCHED_SCAN_DONE || rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
rxd->eid == MCU_EVENT_BSS_ABSENCE || rxd->eid == MCU_EVENT_BSS_ABSENCE ||
rxd->eid == MCU_EVENT_SCAN_DONE || rxd->eid == MCU_EVENT_SCAN_DONE ||
rxd->eid == MCU_EVENT_ROC ||
!rxd->seq) !rxd->seq)
mt7615_mcu_rx_unsolicited_event(dev, skb); mt7615_mcu_rx_unsolicited_event(dev, skb);
else else
@ -2741,11 +2772,9 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)
sizeof(req), true); sizeof(req), true);
} }
void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif)
{ {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_phy *phy = priv;
struct mt76_phy *mphy = phy->mt76;
struct { struct {
u8 bss_idx; u8 bss_idx;
u8 ps_state; /* 0: device awake u8 ps_state; /* 0: device awake
@ -2754,12 +2783,14 @@ void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
*/ */
} req = { } req = {
.bss_idx = mvif->idx, .bss_idx = mvif->idx,
.ps_state = test_bit(MT76_STATE_PS, &mphy->state) ? 2 : 0, .ps_state = vif->bss_conf.ps ? 2 : 0,
}; };
if (vif->type == NL80211_IFTYPE_STATION) if (vif->type != NL80211_IFTYPE_STATION)
__mt76_mcu_send_msg(&phy->dev->mt76, MCU_CMD_SET_PS_PROFILE, return -ENOTSUPP;
&req, sizeof(req), false);
return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE,
&req, sizeof(req), false);
} }
int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy) int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy)
@ -2867,6 +2898,7 @@ int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif,
n_ssids++; n_ssids++;
} }
req->ssid_type = n_ssids ? BIT(2) : BIT(0); req->ssid_type = n_ssids ? BIT(2) : BIT(0);
req->ssid_type_ext = n_ssids ? BIT(0) : 0;
req->ssids_num = n_ssids; req->ssids_num = n_ssids;
/* increase channel time for passive scan */ /* increase channel time for passive scan */
@ -3601,6 +3633,26 @@ int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, int duration)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_dev *dev = phy->dev;
struct mt7615_roc_tlv req = {
.bss_idx = mvif->idx,
.active = !chan,
.max_interval = cpu_to_le32(duration),
.primary_chan = chan ? chan->hw_value : 0,
.band = chan ? chan->band : 0,
.req_type = 2,
};
phy->roc_grant = false;
return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req,
sizeof(req), false);
}
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {

View File

@ -82,6 +82,7 @@ enum {
MCU_EVENT_ACCESS_REG = 0x02, MCU_EVENT_ACCESS_REG = 0x02,
MCU_EVENT_MT_PATCH_SEM = 0x04, MCU_EVENT_MT_PATCH_SEM = 0x04,
MCU_EVENT_SCAN_DONE = 0x0d, MCU_EVENT_SCAN_DONE = 0x0d,
MCU_EVENT_ROC = 0x10,
MCU_EVENT_BSS_ABSENCE = 0x11, MCU_EVENT_BSS_ABSENCE = 0x11,
MCU_EVENT_BSS_BEACON_LOSS = 0x13, MCU_EVENT_BSS_BEACON_LOSS = 0x13,
MCU_EVENT_CH_PRIVILEGE = 0x18, MCU_EVENT_CH_PRIVILEGE = 0x18,
@ -326,7 +327,8 @@ struct mt7615_hw_scan_req {
*/ */
u8 ssid_type; /* BIT(0) wildcard SSID u8 ssid_type; /* BIT(0) wildcard SSID
* BIT(1) P2P wildcard SSID * BIT(1) P2P wildcard SSID
* BIT(2) specified SSID * BIT(2) specified SSID + wildcard SSID
* BIT(2) + ssid_type_ext BIT(0) specified SSID only
*/ */
u8 ssids_num; u8 ssids_num;
u8 probe_req_num; /* Number of probe request for each SSID */ u8 probe_req_num; /* Number of probe request for each SSID */
@ -361,7 +363,8 @@ struct mt7615_hw_scan_req {
struct mt7615_mcu_scan_ssid ext_ssids[6]; struct mt7615_mcu_scan_ssid ext_ssids[6];
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */ u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */
u8 pad[64]; u8 pad[63];
u8 ssid_type_ext;
} __packed; } __packed;
#define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64 #define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64
@ -525,6 +528,23 @@ struct mt7615_gtk_rekey_tlv {
u8 reserverd[3]; u8 reserverd[3];
} __packed; } __packed;
struct mt7615_roc_tlv {
u8 bss_idx;
u8 token;
u8 active;
u8 primary_chan;
u8 sco;
u8 band;
u8 width; /* To support 80/160MHz bandwidth */
u8 freq_seg1; /* To support 80/160MHz bandwidth */
u8 freq_seg2; /* To support 80/160MHz bandwidth */
u8 req_type;
u8 dbdc_band;
u8 rsv0;
__le32 max_interval; /* ms */
u8 rsv1[8];
} __packed;
/* offload mcu commands */ /* offload mcu commands */
enum { enum {
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03, MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
@ -533,6 +553,7 @@ enum {
MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16, MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16,
MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17, MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17,
MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b, MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b,
MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1c,
MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33, MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33,
MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61, MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62, MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,

View File

@ -201,7 +201,10 @@ struct mt7615_phy {
struct sk_buff_head scan_event_list; struct sk_buff_head scan_event_list;
struct delayed_work scan_work; struct delayed_work scan_work;
struct work_struct ps_work; struct work_struct roc_work;
struct timer_list roc_timer;
wait_queue_head_t roc_wait;
bool roc_grant;
}; };
#define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__) #define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__)
@ -411,7 +414,7 @@ static inline bool is_mt7622(struct mt76_dev *dev)
static inline bool is_mt7615(struct mt76_dev *dev) static inline bool is_mt7615(struct mt76_dev *dev)
{ {
return mt76_chip(dev) == 0x7615; return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611;
} }
static inline bool is_mt7663(struct mt76_dev *dev) static inline bool is_mt7663(struct mt76_dev *dev)
@ -419,6 +422,11 @@ static inline bool is_mt7663(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7663; return mt76_chip(dev) == 0x7663;
} }
static inline bool is_mt7611(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7611;
}
static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask)
{ {
mt76_set_irq_mask(&dev->mt76, 0, 0, mask); mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
@ -441,7 +449,8 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev)
void mt7615_dma_reset(struct mt7615_dev *dev); void mt7615_dma_reset(struct mt7615_dev *dev);
void mt7615_scan_work(struct work_struct *work); void mt7615_scan_work(struct work_struct *work);
void mt7615_ps_work(struct work_struct *work); void mt7615_roc_work(struct work_struct *work);
void mt7615_roc_timer(struct timer_list *timer);
void mt7615_init_txpower(struct mt7615_dev *dev, void mt7615_init_txpower(struct mt7615_dev *dev,
struct ieee80211_supported_band *sband); struct ieee80211_supported_band *sband);
void mt7615_phy_init(struct mt7615_dev *dev); void mt7615_phy_init(struct mt7615_dev *dev);
@ -527,11 +536,13 @@ int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index,
int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);
int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy); int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy); int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif);
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, int duration);
int mt7615_firmware_own(struct mt7615_dev *dev); int mt7615_firmware_own(struct mt7615_dev *dev);
int mt7615_driver_own(struct mt7615_dev *dev); int mt7615_driver_own(struct mt7615_dev *dev);

View File

@ -14,6 +14,7 @@
static const struct pci_device_id mt7615_pci_device_table[] = { static const struct pci_device_id mt7615_pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7615) }, { PCI_DEVICE(0x14c3, 0x7615) },
{ PCI_DEVICE(0x14c3, 0x7663) }, { PCI_DEVICE(0x14c3, 0x7663) },
{ PCI_DEVICE(0x14c3, 0x7611) },
{ }, { },
}; };
@ -85,8 +86,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
napi_disable(&mdev->tx_napi); napi_disable(&mdev->tx_napi);
tasklet_kill(&mdev->tx_tasklet); tasklet_kill(&mdev->tx_tasklet);
for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) mt76_for_each_q_rx(mdev, i) {
napi_disable(&mdev->napi[i]); napi_disable(&mdev->napi[i]);
}
tasklet_kill(&dev->irq_tasklet); tasklet_kill(&dev->irq_tasklet);
mt7615_dma_reset(dev); mt7615_dma_reset(dev);
@ -119,8 +121,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
return 0; return 0;
restore: restore:
for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]); napi_enable(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi); napi_enable(&mdev->tx_napi);
if (hif_suspend) if (hif_suspend)
mt7615_mcu_set_hif_suspend(dev, false); mt7615_mcu_set_hif_suspend(dev, false);
@ -155,7 +158,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
if (pdma_reset) if (pdma_reset)
dev_err(mdev->dev, "PDMA engine must be reinitialized\n"); dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) { mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]); napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]); napi_schedule(&mdev->napi[i]);
} }

View File

@ -51,7 +51,8 @@ static void mt7663u_stop(struct ieee80211_hw *hw)
struct mt7615_dev *dev = hw->priv; struct mt7615_dev *dev = hw->priv;
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
cancel_work_sync(&phy->ps_work); del_timer_sync(&phy->roc_timer);
cancel_work_sync(&phy->roc_work);
cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->scan_work);
cancel_delayed_work_sync(&phy->mac_work); cancel_delayed_work_sync(&phy->mac_work);
mt76u_stop_tx(&dev->mt76); mt76u_stop_tx(&dev->mt76);

View File

@ -15,6 +15,7 @@
#include "mt76x02_dfs.h" #include "mt76x02_dfs.h"
#include "mt76x02_dma.h" #include "mt76x02_dma.h"
#define MT76x02_N_WCIDS 128
#define MT_CALIBRATE_INTERVAL HZ #define MT_CALIBRATE_INTERVAL HZ
#define MT_MAC_WORK_INTERVAL (HZ / 10) #define MT_MAC_WORK_INTERVAL (HZ / 10)
@ -246,7 +247,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx)
{ {
struct mt76_wcid *wcid; struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->wcid)) if (idx >= MT76x02_N_WCIDS)
return NULL; return NULL;
wcid = rcu_dereference(dev->wcid[idx]); wcid = rcu_dereference(dev->wcid[idx]);

View File

@ -561,7 +561,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
rcu_read_lock(); rcu_read_lock();
if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid)) if (stat->wcid < MT76x02_N_WCIDS)
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
if (wcid && wcid->sta) { if (wcid && wcid->sta) {

View File

@ -20,7 +20,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int ret; int ret;
u8 seq; u8 seq;
if (mt76_is_mmio(&dev->mt76) && dev->mcu_timeout) if (dev->mcu_timeout)
return -EIO; return -EIO;
skb = mt76_mcu_msg_alloc(mdev, data, len); skb = mt76_mcu_msg_alloc(mdev, data, len);

View File

@ -415,7 +415,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev)
ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL);
rcu_read_unlock(); rcu_read_unlock();
for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) { for (i = 0; i < MT76x02_N_WCIDS; i++) {
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct mt76x02_sta *msta; struct mt76x02_sta *msta;
@ -489,8 +489,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++) for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true); mt76_queue_tx_cleanup(dev, i, true);
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i); mt76_queue_rx_reset(dev, i);
}
mt76x02_mac_start(dev); mt76x02_mac_start(dev);

View File

@ -249,7 +249,7 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
memset(msta, 0, sizeof(*msta)); memset(msta, 0, sizeof(*msta));
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT76x02_N_WCIDS);
if (idx < 0) if (idx < 0)
return -ENOSPC; return -ENOSPC;

View File

@ -173,14 +173,14 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
/* Tx Beamformee Rx NDPA & Tx feedback report */ /* Tx Beamformee Rx NDPA & Tx feedback report */
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy)); cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
seq_printf(s, "Tx Beamformee sucessful feedback frames: %ld\n", seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n",
FIELD_GET(MT_ETBF_TX_FB_CPL, cnt)); FIELD_GET(MT_ETBF_TX_FB_CPL, cnt));
seq_printf(s, "Tx Beamformee feedback triggerd counts: %ld\n", seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n",
FIELD_GET(MT_ETBF_TX_FB_TRI, cnt)); FIELD_GET(MT_ETBF_TX_FB_TRI, cnt));
/* Tx SU counters */ /* Tx SU counters */
cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy)); cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));
seq_printf(s, "Tx single-user sucessful MPDU counts: %d\n", cnt); seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt);
seq_puts(s, "\n"); seq_puts(s, "\n");
} }

View File

@ -592,7 +592,6 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)
if (phy) if (phy)
return 0; return 0;
INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
mt7915_cap_dbdc_enable(dev); mt7915_cap_dbdc_enable(dev);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
if (!mphy) if (!mphy)
@ -605,6 +604,8 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mt7915_init_wiphy(mphy->hw); mt7915_init_wiphy(mphy->hw);
INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
/* /*
* Make the secondary PHY MAC address local without overlapping with * Make the secondary PHY MAC address local without overlapping with
* the usual MAC address allocation scheme on multiple virtual interfaces * the usual MAC address allocation scheme on multiple virtual interfaces

View File

@ -235,9 +235,14 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
HE_BITS(DATA1_DATA_DCM_KNOWN) | HE_BITS(DATA1_DATA_DCM_KNOWN) |
HE_BITS(DATA1_STBC_KNOWN) | HE_BITS(DATA1_STBC_KNOWN) |
HE_BITS(DATA1_CODING_KNOWN), HE_BITS(DATA1_CODING_KNOWN) |
HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
HE_BITS(DATA1_DOPPLER_KNOWN) |
HE_BITS(DATA1_BSS_COLOR_KNOWN),
.data2 = HE_BITS(DATA2_GI_KNOWN) | .data2 = HE_BITS(DATA2_GI_KNOWN) |
HE_BITS(DATA2_TXBF_KNOWN), HE_BITS(DATA2_TXBF_KNOWN) |
HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
HE_BITS(DATA2_TXOP_KNOWN),
}; };
struct ieee80211_radiotap_he *he = NULL; struct ieee80211_radiotap_he *he = NULL;
__le32 v2 = rxv->v[2]; __le32 v2 = rxv->v[2];
@ -248,12 +253,6 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
he = skb_push(skb, sizeof(known)); he = skb_push(skb, sizeof(known));
memcpy(he, &known, sizeof(known)); memcpy(he, &known, sizeof(known));
he->data1 = HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
HE_BITS(DATA1_DOPPLER_KNOWN) |
HE_BITS(DATA1_BSS_COLOR_KNOWN);
he->data2 = HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
HE_BITS(DATA2_TXOP_KNOWN);
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, v14) | he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, v14) |
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, v2); HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, v2);
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, v2) | he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, v2) |
@ -296,10 +295,10 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE4_KNOWN); HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
he->data4 = HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) | he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) |
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) | HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) |
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) | HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) |
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11); HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11);
mt7915_mac_decode_he_radiotap_ru(status, rxv, he); mt7915_mac_decode_he_radiotap_ru(status, rxv, he);
break; break;
@ -426,20 +425,26 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
/* RXD Group 3 - P-RXV */ /* RXD Group 3 - P-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
u32 v0, v1, v2;
memcpy(rxv.v, rxd, sizeof(rxv.v)); memcpy(rxv.v, rxd, sizeof(rxv.v));
rxd += 2; rxd += 2;
if ((u8 *)rxd - skb->data >= skb->len) if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL; return -EINVAL;
if (rxv.v[0] & MT_PRXV_HT_AD_CODE) v0 = le32_to_cpu(rxv.v[0]);
v1 = le32_to_cpu(rxv.v[1]);
v2 = le32_to_cpu(rxv.v[2]);
if (v0 & MT_PRXV_HT_AD_CODE)
status->enc_flags |= RX_ENC_FLAG_LDPC; status->enc_flags |= RX_ENC_FLAG_LDPC;
status->chains = mphy->antenna_mask; status->chains = mphy->antenna_mask;
status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, rxv.v[1]); status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1);
status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, rxv.v[1]); status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1);
status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, rxv.v[1]); status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1);
status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, rxv.v[1]); status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1);
status->signal = status->chain_signal[0]; status->signal = status->chain_signal[0];
for (i = 1; i < hweight8(mphy->antenna_mask); i++) { for (i = 1; i < hweight8(mphy->antenna_mask); i++) {
@ -452,16 +457,16 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
/* RXD Group 5 - C-RXV */ /* RXD Group 5 - C-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, rxv.v[2]); u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, rxv.v[2]); u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
bool cck = false; bool cck = false;
rxd += 18; rxd += 18;
if ((u8 *)rxd - skb->data >= skb->len) if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL; return -EINVAL;
idx = i = FIELD_GET(MT_PRXV_TX_RATE, rxv.v[0]); idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, rxv.v[2]); rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, v2);
switch (rxv.phy) { switch (rxv.phy) {
case MT_PHY_TYPE_CCK: case MT_PHY_TYPE_CCK:
@ -478,7 +483,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
break; break;
case MT_PHY_TYPE_VHT: case MT_PHY_TYPE_VHT:
status->nss = status->nss =
FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; FIELD_GET(MT_PRXV_NSTS, v0) + 1;
status->encoding = RX_ENC_VHT; status->encoding = RX_ENC_VHT;
if (i > 9) if (i > 9)
return -EINVAL; return -EINVAL;
@ -490,7 +495,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
case MT_PHY_TYPE_HE_EXT_SU: case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB: case MT_PHY_TYPE_HE_TB:
status->nss = status->nss =
FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; FIELD_GET(MT_PRXV_NSTS, v0) + 1;
status->encoding = RX_ENC_HE; status->encoding = RX_ENC_HE;
status->flag |= RX_FLAG_RADIOTAP_HE; status->flag |= RX_FLAG_RADIOTAP_HE;
i &= GENMASK(3, 0); i &= GENMASK(3, 0);
@ -506,7 +511,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
} }
status->rate_idx = i; status->rate_idx = i;
switch (FIELD_GET(MT_CRXV_FRAME_MODE, rxv.v[2])) { switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) {
case IEEE80211_STA_RX_BW_20: case IEEE80211_STA_RX_BW_20:
break; break;
case IEEE80211_STA_RX_BW_40: case IEEE80211_STA_RX_BW_40:
@ -612,7 +617,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
skb->priority & IEEE80211_QOS_CTL_TID_MASK) | skb->priority & IEEE80211_QOS_CTL_TID_MASK) |
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
val |= cpu_to_le32(MT_TXD1_TGID); val |= MT_TXD1_TGID;
txwi[1] = cpu_to_le32(val); txwi[1] = cpu_to_le32(val);
@ -1141,8 +1146,9 @@ mt7915_dma_reset(struct mt7915_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++) for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true); mt76_queue_tx_cleanup(dev, i, true);
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i); mt76_queue_rx_reset(dev, i);
}
/* re-init prefetch settings after reset */ /* re-init prefetch settings after reset */
mt7915_dma_prefetch(dev); mt7915_dma_prefetch(dev);

View File

@ -437,8 +437,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
mt7915_mcu_add_sta(dev, vif, NULL, join); mt7915_mcu_add_sta(dev, vif, NULL, join);
} }
if (changed & BSS_CHANGED_ASSOC) if (changed & BSS_CHANGED_ASSOC) {
mt7915_mcu_add_bss_info(phy, vif, info->assoc); mt7915_mcu_add_bss_info(phy, vif, info->assoc);
mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
}
if (changed & BSS_CHANGED_ERP_SLOT) { if (changed & BSS_CHANGED_ERP_SLOT) {
int slottime = info->use_short_slot ? 9 : 20; int slottime = info->use_short_slot ? 9 : 20;
@ -458,6 +460,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_set_tx(dev, vif); mt7915_mcu_set_tx(dev, vif);
if (changed & BSS_CHANGED_HE_OBSS_PD)
mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
if (changed & (BSS_CHANGED_BEACON | if (changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED)) BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
@ -790,7 +795,7 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw,
rcu_read_unlock(); rcu_read_unlock();
return; return;
} }
rcu_read_lock(); rcu_read_unlock();
set_bit(changed, &msta->stats.changed); set_bit(changed, &msta->stats.changed);
ieee80211_queue_work(hw, &msta->stats_work); ieee80211_queue_work(hw, &msta->stats_work);

View File

@ -220,7 +220,7 @@ static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb,
{ {
struct mt7915_mcu_txd *mcu_txd; struct mt7915_mcu_txd *mcu_txd;
u8 seq, pkt_fmt, qidx; u8 seq, pkt_fmt, qidx;
enum mt7915_txq_id txq; enum mt76_txq_id txq;
__le32 *txd; __le32 *txd;
u32 val; u32 val;
@ -815,8 +815,7 @@ static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
struct mt7915_he_obss_narrow_bw_ru_data *data = _data; struct mt7915_he_obss_narrow_bw_ru_data *data = _data;
const struct element *elem; const struct element *elem;
elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data, elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY);
bss->ies->len);
if (!elem || elem->datalen < 10 || if (!elem || elem->datalen < 10 ||
!(elem->data[10] & !(elem->data[10] &
@ -1802,15 +1801,12 @@ static u8
mt7915_mcu_sta_txbf_type(struct mt7915_phy *phy, struct ieee80211_vif *vif, mt7915_mcu_sta_txbf_type(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct mt7915_sta *msta;
u8 type = 0; u8 type = 0;
if (vif->type != NL80211_IFTYPE_STATION && if (vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_AP) vif->type != NL80211_IFTYPE_AP)
return 0; return 0;
msta = (struct mt7915_sta *)sta->drv_priv;
if (sta->he_cap.has_he) { if (sta->he_cap.has_he) {
struct ieee80211_he_cap_elem *pe; struct ieee80211_he_cap_elem *pe;
const struct ieee80211_he_cap_elem *ve; const struct ieee80211_he_cap_elem *ve;
@ -1954,7 +1950,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
ra->supp_mode |= MODE_HT; ra->supp_mode |= MODE_HT;
mcs = hweight32(ra->supp_ht_mcs) - 1; mcs = hweight32(le32_to_cpu(ra->supp_ht_mcs)) - 1;
ra->af = sta->ht_cap.ampdu_factor; ra->af = sta->ht_cap.ampdu_factor;
ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
@ -1972,7 +1968,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
} }
if (sta->vht_cap.vht_supported) { if (sta->vht_cap.vht_supported) {
__le16 mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
u16 vht_mcs; u16 vht_mcs;
u8 af, mcs_prev; u8 af, mcs_prev;
@ -2399,7 +2395,7 @@ static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr,
}; };
int attr; int attr;
if (req.addr == MCU_PATCH_ADDRESS) if (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS))
attr = -MCU_CMD_PATCH_START_REQ; attr = -MCU_CMD_PATCH_START_REQ;
else else
attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ; attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ;
@ -2672,7 +2668,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level)
u16 len; u16 len;
u8 level; u8 level;
u8 rsv[3]; u8 rsv[3];
u32 module_idx; __le32 module_idx;
} data = { } data = {
.module_idx = cpu_to_le32(module), .module_idx = cpu_to_le32(module),
.level = level, .level = level,
@ -3159,3 +3155,28 @@ int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev)
return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION,
&req, sizeof(req), true); &req, sizeof(req), true);
} }
int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
#define MT_SPR_ENABLE 1
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct {
u8 action;
u8 arg_num;
u8 band_idx;
u8 status;
u8 drop_tx_idx;
u8 sta_idx; /* 256 sta */
u8 rsv[2];
u32 val;
} __packed req = {
.action = MT_SPR_ENABLE,
.arg_num = 1,
.band_idx = mvif->band_idx,
.val = enable,
};
return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR,
&req, sizeof(req), true);
}

View File

@ -212,6 +212,7 @@ enum {
MCU_EXT_CMD_RATE_CTRL = 0x87, MCU_EXT_CMD_RATE_CTRL = 0x87,
MCU_EXT_CMD_FW_DBG_CTRL = 0x95, MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
MCU_EXT_CMD_SET_RDD_TH = 0x9d, MCU_EXT_CMD_SET_RDD_TH = 0x9d,
MCU_EXT_CMD_SET_SPR = 0xa8,
}; };
enum { enum {

View File

@ -301,6 +301,8 @@ int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif,
enum set_key_cmd cmd); enum set_key_cmd cmd);
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int enable); int enable);
int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,

View File

@ -42,17 +42,17 @@ bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
} }
EXPORT_SYMBOL_GPL(__mt76_poll_msec); EXPORT_SYMBOL_GPL(__mt76_poll_msec);
int mt76_wcid_alloc(unsigned long *mask, int size) int mt76_wcid_alloc(u32 *mask, int size)
{ {
int i, idx = 0, cur; int i, idx = 0, cur;
for (i = 0; i < DIV_ROUND_UP(size, BITS_PER_LONG); i++) { for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
idx = ffs(~mask[i]); idx = ffs(~mask[i]);
if (!idx) if (!idx)
continue; continue;
idx--; idx--;
cur = i * BITS_PER_LONG + idx; cur = i * 32 + idx;
if (cur >= size) if (cur >= size)
break; break;
@ -74,13 +74,13 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy)
rcu_read_lock(); rcu_read_lock();
for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
unsigned long mask = dev->wcid_mask[i]; u32 mask = dev->wcid_mask[i];
unsigned long phy_mask = dev->wcid_phy_mask[i]; u32 phy_mask = dev->wcid_phy_mask[i];
if (!mask) if (!mask)
continue; continue;
for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1, phy_mask >>= 1) { for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) {
if (!(mask & 1)) if (!(mask & 1))
continue; continue;

View File

@ -14,24 +14,24 @@
#define MT76_INCR(_var, _size) \ #define MT76_INCR(_var, _size) \
(_var = (((_var) + 1) % (_size))) (_var = (((_var) + 1) % (_size)))
int mt76_wcid_alloc(unsigned long *mask, int size); int mt76_wcid_alloc(u32 *mask, int size);
static inline bool static inline bool
mt76_wcid_mask_test(unsigned long *mask, int idx) mt76_wcid_mask_test(u32 *mask, int idx)
{ {
return mask[idx / BITS_PER_LONG] & BIT(idx % BITS_PER_LONG); return mask[idx / 32] & BIT(idx % 32);
} }
static inline void static inline void
mt76_wcid_mask_set(unsigned long *mask, int idx) mt76_wcid_mask_set(u32 *mask, int idx)
{ {
mask[idx / BITS_PER_LONG] |= BIT(idx % BITS_PER_LONG); mask[idx / 32] |= BIT(idx % 32);
} }
static inline void static inline void
mt76_wcid_mask_clear(unsigned long *mask, int idx) mt76_wcid_mask_clear(u32 *mask, int idx)
{ {
mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG); mask[idx / 32] &= ~BIT(idx % 32);
} }
static inline void static inline void