Skip to content

Commit

Permalink
mt76: mt7915: introduce dbdc support
Browse files Browse the repository at this point in the history
Introduce mt7915 dbdc support. If dbdc is available, mt7915 primary phy
will work on 2.4GHz band, while secondary one on 5GHz band.

Co-developed-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
LorenzoBianconi authored and nbd168 committed Nov 13, 2020
1 parent 8aa24c9 commit b436da4
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 104 deletions.
1 change: 1 addition & 0 deletions mt76.h
Expand Up @@ -80,6 +80,7 @@ enum mt76_rxq_id {
MT_RXQ_MAIN,
MT_RXQ_MCU,
MT_RXQ_MCU_WA,
MT_RXQ_EXT,
__MT_RXQ_MAX
};

Expand Down
13 changes: 10 additions & 3 deletions mt7915/debugfs.c
Expand Up @@ -280,20 +280,27 @@ static int
mt7915_queues_read(struct seq_file *s, void *data)
{
struct mt7915_dev *dev = dev_get_drvdata(s->private);
struct mt76_phy *mphy_ext = dev->mt76.phy2;
struct mt76_queue *ext_q = mphy_ext ? mphy_ext->q_tx[MT_TXQ_BE] : NULL;
struct {
struct mt76_queue *q;
char *queue;
} queue_map[] = {
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_WA], "MCUWA" },
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ ext_q, "WFDMA1" },
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_WA], "MCUWA" },
{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
};
int i;

for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_queue *q = queue_map[i].q;

if (!q)
continue;

seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
queue_map[i].queue, q->queued, q->head,
Expand Down
19 changes: 13 additions & 6 deletions mt7915/dma.c
Expand Up @@ -5,8 +5,7 @@
#include "../dma.h"
#include "mac.h"

static int
mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc)
int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc)
{
int i, err;

Expand Down Expand Up @@ -274,13 +273,21 @@ int mt7915_dma_init(struct mt7915_dev *dev)
if (ret)
return ret;

/* rx data */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
MT7915_RX_RING_SIZE, rx_buf_size,
MT_RX_DATA_RING_BASE);
/* rx data queue */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT7915_RXQ_BAND0, MT7915_RX_RING_SIZE,
rx_buf_size, MT_RX_DATA_RING_BASE);
if (ret)
return ret;

if (dev->dbdc_support) {
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE,
rx_buf_size, MT_RX_DATA_RING_BASE);
if (ret)
return ret;
}

ret = mt76_init_queues(dev);
if (ret < 0)
return ret;
Expand Down
47 changes: 31 additions & 16 deletions mt7915/eeprom.c
Expand Up @@ -43,35 +43,50 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev)
}
}

static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev)
void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
{
u8 *eeprom = dev->mt76.eeprom.data;
u8 tx_mask, max_nss = 4;
u32 val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF);
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
u32 val;

val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy);
val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val);
switch (val) {
case MT_EE_5GHZ:
dev->mphy.cap.has_5ghz = true;
phy->mt76->cap.has_5ghz = true;
break;
case MT_EE_2GHZ:
dev->mphy.cap.has_2ghz = true;
phy->mt76->cap.has_2ghz = true;
break;
default:
dev->mphy.cap.has_2ghz = true;
dev->mphy.cap.has_5ghz = true;
phy->mt76->cap.has_2ghz = true;
phy->mt76->cap.has_5ghz = true;
break;
}
}

static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev)
{
u8 nss, tx_mask[2] = {}, *eeprom = dev->mt76.eeprom.data;

mt7915_eeprom_parse_band_config(&dev->phy);

/* read tx mask from eeprom */
tx_mask = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK,
eeprom[MT_EE_WIFI_CONF]);
if (!tx_mask || tx_mask > max_nss)
tx_mask = max_nss;

dev->chainmask = BIT(tx_mask) - 1;
dev->mphy.antenna_mask = dev->chainmask;
dev->phy.chainmask = dev->chainmask;
tx_mask[0] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK,
eeprom[MT_EE_WIFI_CONF]);
if (dev->dbdc_support)
tx_mask[1] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK,
eeprom[MT_EE_WIFI_CONF + 1]);

nss = tx_mask[0] + tx_mask[1];
if (!nss || nss > 4) {
tx_mask[0] = 4;
nss = 4;
}

dev->chainmask = BIT(nss) - 1;
dev->mphy.antenna_mask = BIT(tx_mask[0]) - 1;
dev->phy.chainmask = dev->mphy.antenna_mask;
}

int mt7915_eeprom_init(struct mt7915_dev *dev)
Expand Down
1 change: 1 addition & 0 deletions mt7915/eeprom.h
Expand Up @@ -15,6 +15,7 @@ enum mt7915_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_MAC_ADDR2 = 0x00a,
MT_EE_DDIE_FT_VERSION = 0x050,
MT_EE_WIFI_CONF = 0x190,
MT_EE_RATE_DELTA_2G = 0x252,
Expand Down
102 changes: 41 additions & 61 deletions mt7915/init.c
Expand Up @@ -35,25 +35,26 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)

mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);

mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
/* disable rx rate report by default due to hw issues */
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
}

static void mt7915_mac_init(struct mt7915_dev *dev)
{
int i;

mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_MAX_RX_LEN, 1536);
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
/* disable rx rate report by default due to hw issues */
mt76_clear(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN);
/* disable hardware de-agg */
mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);

for (i = 0; i < MT7915_WTBL_SIZE; i++)
mt7915_mac_wtbl_update(dev, i,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
for (i = 0; i < 2; i++)
mt7915_mac_init_band(dev, i);

mt7915_mac_init_band(dev, 0);
mt7915_mac_init_band(dev, 1);
mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b);
}

Expand Down Expand Up @@ -119,6 +120,7 @@ static void mt7915_init_work(struct work_struct *work)
mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
mt7915_txbf_init(dev);
mt7915_register_ext_phy(dev);
}

static int mt7915_init_hardware(struct mt7915_dev *dev)
Expand All @@ -131,6 +133,8 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
spin_lock_init(&dev->token_lock);
idr_init(&dev->token);

dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5));

ret = mt7915_dma_init(dev);
if (ret)
return ret;
Expand Down Expand Up @@ -548,63 +552,18 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
}
}

static void
mt7915_cap_dbdc_enable(struct mt7915_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;
dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;

mt76_set_stream_caps(&dev->mphy, true);
mt7915_set_stream_vht_txbf_caps(&dev->phy);
mt7915_set_stream_he_caps(&dev->phy);
}

static void
mt7915_cap_dbdc_disable(struct mt7915_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;
dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;

mt76_set_stream_caps(&dev->mphy, true);
mt7915_set_stream_vht_txbf_caps(&dev->phy);
mt7915_set_stream_he_caps(&dev->phy);
}

int mt7915_register_ext_phy(struct mt7915_dev *dev)
{
struct mt7915_phy *phy = mt7915_ext_phy(dev);
struct mt76_phy *mphy;
int ret;
bool bound;

/* TODO: enble DBDC */
bound = mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5);
if (!bound)
return -EINVAL;

if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
return -EINVAL;
if (!dev->dbdc_support)
return 0;

if (phy)
return 0;

mt7915_cap_dbdc_enable(dev);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
if (!mphy)
return -ENOMEM;
Expand All @@ -619,18 +578,31 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)
INIT_LIST_HEAD(&phy->stats_list);
INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);

/*
* 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);
mt7915_eeprom_parse_band_config(phy);
mt7915_set_stream_vht_txbf_caps(phy);
mt7915_set_stream_he_caps(phy);

memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,
ETH_ALEN);
mt76_eeprom_override(mphy);

/* The second interface does not get any packets unless it has a vif */
ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF);

ret = mt7915_init_tx_queues(phy, MT7915_TXQ_BAND1,
MT7915_TX_RING_SIZE);
if (ret)
goto error;

ret = mt76_register_phy(mphy, true, mt7915_rates,
ARRAY_SIZE(mt7915_rates));
if (ret)
ieee80211_free_hw(mphy->hw);
goto error;

return 0;

error:
ieee80211_free_hw(mphy->hw);
return ret;
}

Expand All @@ -642,7 +614,6 @@ void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
if (!phy)
return;

mt7915_cap_dbdc_disable(dev);
mt76_unregister_phy(mphy);
ieee80211_free_hw(mphy->hw);
}
Expand Down Expand Up @@ -679,7 +650,16 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
mt7915_cap_dbdc_disable(dev);
if (!dev->dbdc_support)
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;

mt76_set_stream_caps(&dev->mphy, true);
mt7915_set_stream_vht_txbf_caps(&dev->phy);
mt7915_set_stream_he_caps(&dev->phy);
dev->phy.dfs_state = -1;

#ifdef CONFIG_NL80211_TESTMODE
Expand Down
14 changes: 11 additions & 3 deletions mt7915/mac.c
Expand Up @@ -1077,6 +1077,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data;
struct mt76_dev *mdev = &dev->mt76;
struct mt76_phy *mphy_ext = mdev->phy2;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
LIST_HEAD(free_list);
Expand All @@ -1086,6 +1087,10 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
/* clean DMA queues and unmap buffers first */
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
if (mphy_ext) {
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false);
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
}

/*
* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE,
Expand Down Expand Up @@ -1321,9 +1326,8 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
u32 val, sum = 0, n = 0;
int nss, i;

/* TODO: DBDC: 0,1 for 2.4G, 2,3 for 5G */
for (nss = 0; nss < hweight8(phy->chainmask); nss++) {
u32 reg = MT_WF_IRPI(nss);
u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support));

for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {
val = mt7915_l2_rr(dev, reg);
Expand Down Expand Up @@ -1425,6 +1429,7 @@ static void
mt7915_dma_reset(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct mt76_phy *mphy_ext = dev->mt76.phy2;
int i;

mt76_clear(dev, MT_WFDMA0_GLO_CFG,
Expand All @@ -1434,8 +1439,11 @@ mt7915_dma_reset(struct mt7915_phy *phy)
usleep_range(1000, 2000);

mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true);
for (i = 0; i < __MT_TXQ_MAX; i++)
for (i = 0; i < __MT_TXQ_MAX; i++) {
mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true);
if (mphy_ext)
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
}

mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
Expand Down
3 changes: 2 additions & 1 deletion mt7915/main.c
Expand Up @@ -394,7 +394,8 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
else
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;

mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN, enabled);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
enabled);
mt76_testmode_reset(&dev->mt76, true);
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
}
Expand Down

0 comments on commit b436da4

Please sign in to comment.