From 993683d62fb7895e917b636b82f8f9f6a587f0e1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 23:27:48 +0100 Subject: [PATCH] mt76: mt7615: add support for registering a second wiphy via debugfs This is only used for testing for now. In the future it will be possible to enable the second PHY through an proper API via device tree Signed-off-by: Felix Fietkau --- mt7615/debugfs.c | 27 +++++++++++ mt7615/eeprom.c | 5 +- mt7615/init.c | 118 +++++++++++++++++++++++++++++++++++++++-------- mt7615/mt7615.h | 4 ++ 4 files changed, 133 insertions(+), 21 deletions(-) diff --git a/mt7615/debugfs.c b/mt7615/debugfs.c index 05a0172b..f75b3f66 100644 --- a/mt7615/debugfs.c +++ b/mt7615/debugfs.c @@ -36,6 +36,32 @@ mt7615_scs_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get, mt7615_scs_set, "%lld\n"); +static int +mt7615_dbdc_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (val) + mt7615_register_ext_phy(dev); + else + mt7615_unregister_ext_phy(dev); + + return 0; +} + +static int +mt7615_dbdc_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = !!mt7615_ext_phy(dev); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get, + mt7615_dbdc_set, "%lld\n"); + static int mt7615_ampdu_stat_read(struct seq_file *file, void *data) { @@ -183,6 +209,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) mt7615_queues_acq); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("scs", 0600, dir, dev, &fops_scs); + debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); diff --git a/mt7615/eeprom.c b/mt7615/eeprom.c index 61a3fba2..e4dcfa53 100644 --- a/mt7615/eeprom.c +++ b/mt7615/eeprom.c @@ -124,8 +124,9 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) if (!tx_mask || tx_mask > max_nss) tx_mask = max_nss; - dev->mphy.antenna_mask = BIT(tx_mask) - 1; - dev->phy.chainmask = dev->mphy.antenna_mask; + dev->chainmask = BIT(tx_mask) - 1; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; } int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, diff --git a/mt7615/init.c b/mt7615/init.c index 005cf360..10043ca2 100644 --- a/mt7615/init.c +++ b/mt7615/init.c @@ -262,22 +262,10 @@ mt7615_regd_notifier(struct wiphy *wiphy, mt7615_dfs_init_radar_detector(phy); } -int mt7615_register_device(struct mt7615_dev *dev) +static void +mt7615_init_wiphy(struct ieee80211_hw *hw) { - struct ieee80211_hw *hw = mt76_hw(dev); struct wiphy *wiphy = hw->wiphy; - int ret; - - dev->phy.dev = dev; - dev->phy.mt76 = &dev->mt76.phy; - dev->mt76.phy.priv = &dev->phy; - INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); - - ret = mt7615_init_hardware(dev); - if (ret) - return ret; hw->queues = 4; hw->max_rates = 3; @@ -296,13 +284,106 @@ int mt7615_register_device(struct mt7615_dev *dev) ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; +} + +static void +mt7615_cap_dbdc_enable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap &= + ~(IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); + if (dev->chainmask == 0xf) + dev->mphy.antenna_mask = dev->chainmask >> 2; + else + dev->mphy.antenna_mask = dev->chainmask >> 1; + dev->phy.chainmask = dev->mphy.antenna_mask; + mt76_set_stream_caps(&dev->mt76, true); +} + +static void +mt7615_cap_dbdc_disable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; + mt76_set_stream_caps(&dev->mt76, true); +} + +int mt7615_register_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy; + int ret; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return -EINVAL; + + if (phy) + return 0; + + mt7615_cap_dbdc_enable(dev); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); + if (!mphy) + return -ENOMEM; + + phy = mphy->priv; + phy->dev = dev; + phy->mt76 = mphy; + phy->chainmask = dev->chainmask & ~dev->phy.chainmask; + mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; + mt7615_init_wiphy(mphy->hw); + + /* second phy can only handle 5 GHz */ + mphy->sband_2g.sband.n_channels = 0; + mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + + ret = mt76_register_phy(mphy); + if (ret) + ieee80211_free_hw(mphy->hw); + + return ret; +} + +void mt7615_unregister_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy = dev->mt76.phy2; + + if (!phy) + return; + + mt7615_cap_dbdc_disable(dev); + mt76_unregister_phy(mphy); + ieee80211_free_hw(mphy->hw); +} + + +int mt7615_register_device(struct mt7615_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + int ret; + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); + INIT_LIST_HEAD(&dev->sta_poll_list); + spin_lock_init(&dev->sta_poll_lock); + + ret = mt7615_init_hardware(dev); + if (ret) + return ret; + + mt7615_init_wiphy(hw); dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_SHORT_GI_160 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + mt7615_cap_dbdc_disable(dev); dev->phy.dfs_state = -1; ret = mt76_register_device(&dev->mt76, true, mt7615_rates, @@ -313,8 +394,6 @@ int mt7615_register_device(struct mt7615_dev *dev) mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); - hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; - return mt7615_init_debugfs(dev); } @@ -323,6 +402,7 @@ void mt7615_unregister_device(struct mt7615_dev *dev) struct mt76_txwi_cache *txwi; int id; + mt7615_unregister_ext_phy(dev); mt76_unregister_device(&dev->mt76); mt7615_mcu_exit(dev); mt7615_dma_cleanup(dev); diff --git a/mt7615/mt7615.h b/mt7615/mt7615.h index 2adf3b8a..32f23f5f 100644 --- a/mt7615/mt7615.h +++ b/mt7615/mt7615.h @@ -115,6 +115,8 @@ struct mt7615_dev { u32 vif_mask; u32 omac_mask; + u16 chainmask; + struct list_head sta_poll_list; spinlock_t sta_poll_lock; @@ -211,6 +213,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); +int mt7615_register_ext_phy(struct mt7615_dev *dev); +void mt7615_unregister_ext_phy(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, struct ieee80211_channel *chan,