mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-29 10:34:22 -04:00
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 Running: echo 1 > /sys/kernel/debug/ieee80211/phyX/mt76/dbdc will register a second wiphy (and limit the primary one to 2 spatial streams). The second wiphy will only be able to run on 5 GHz, while the primary one can operate in both bands (if supported by the device). Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -125,8 +125,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,
|
||||
|
||||
@@ -256,22 +256,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;
|
||||
@@ -290,13 +278,113 @@ 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);
|
||||
|
||||
/*
|
||||
* Make the secondary PHY MAC address local without overlapping with
|
||||
* the usual MAC address allocation scheme on multiple virtual interfaces
|
||||
*/
|
||||
mphy->hw->wiphy->perm_addr[0] |= 2;
|
||||
mphy->hw->wiphy->perm_addr[0] ^= BIT(7);
|
||||
|
||||
/* 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,
|
||||
@@ -307,8 +395,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);
|
||||
}
|
||||
|
||||
@@ -317,6 +403,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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user