diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/init.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/init.c | 220 |
1 files changed, 147 insertions, 73 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index ad4e5b95158b..822f3aa6bb8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -4,6 +4,7 @@ #include <linux/etherdevice.h> #include "mt7915.h" #include "mac.h" +#include "mcu.h" #include "eeprom.h" #define CCK_RATE(_idx, _rate) { \ @@ -67,6 +68,39 @@ static const struct ieee80211_iface_combination if_comb[] = { }; static void +mt7915_init_txpower(struct mt7915_dev *dev, + struct ieee80211_supported_band *sband) +{ + int i, n_chains = hweight8(dev->mphy.antenna_mask); + int nss_delta = mt76_tx_power_nss_delta(n_chains); + int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band); + struct mt76_power_limits limits; + + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *chan = &sband->channels[i]; + u32 target_power = 0; + int j; + + for (j = 0; j < n_chains; j++) { + u32 val; + + val = mt7915_eeprom_get_target_power(dev, chan, j); + target_power = max(target_power, val); + } + + target_power += pwr_delta; + target_power = mt76_get_rate_power_limits(&dev->mphy, chan, + &limits, + target_power); + target_power += nss_delta; + target_power = DIV_ROUND_UP(target_power, 2); + chan->max_power = min_t(int, chan->max_reg_power, + target_power); + chan->orig_mpwr = target_power; + } +} + +static void mt7915_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { @@ -76,8 +110,12 @@ mt7915_regd_notifier(struct wiphy *wiphy, struct mt7915_phy *phy = mphy->priv; struct cfg80211_chan_def *chandef = &mphy->chandef; + memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; + mt7915_init_txpower(dev, &mphy->sband_2g.sband); + mt7915_init_txpower(dev, &mphy->sband_5g.sband); + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) return; @@ -93,6 +131,10 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) hw->queues = 4; hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + hw->netdev_features = NETIF_F_RXCSUM; + + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; phy->slottime = 9; @@ -108,9 +150,28 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); ieee80211_hw_set(hw, WANT_MONITOR_VIF); hw->max_tx_fragments = 4; + + if (phy->mt76->cap.has_2ghz) + phy->mt76->sband_2g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + + if (phy->mt76->cap.has_5ghz) { + phy->mt76->sband_5g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + } + + mt76_set_stream_caps(phy->mt76, true); + mt7915_set_stream_vht_txbf_caps(phy); + mt7915_set_stream_he_caps(phy); } static void @@ -153,16 +214,14 @@ static void mt7915_mac_init(struct mt7915_dev *dev) int i; mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); - /* disable hardware de-agg */ - mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); + /* enable hardware de-agg */ + mt76_set(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_mcu_set_rts_thresh(&dev->phy, 0x92b); } static int mt7915_txbf_init(struct mt7915_dev *dev) @@ -185,38 +244,6 @@ static int mt7915_txbf_init(struct mt7915_dev *dev) return mt7915_mcu_set_txbf_type(dev); } -static void -mt7915_init_txpower_band(struct mt7915_dev *dev, - struct ieee80211_supported_band *sband) -{ - int i, n_chains = hweight8(dev->mphy.antenna_mask); - - for (i = 0; i < sband->n_channels; i++) { - struct ieee80211_channel *chan = &sband->channels[i]; - u32 target_power = 0; - int j; - - for (j = 0; j < n_chains; j++) { - u32 val; - - val = mt7915_eeprom_get_target_power(dev, chan, j); - target_power = max(target_power, val); - } - - chan->max_power = min_t(int, chan->max_reg_power, - target_power / 2); - chan->orig_mpwr = target_power / 2; - } -} - -static void mt7915_init_txpower(struct mt7915_dev *dev) -{ - mt7915_init_txpower_band(dev, &dev->mphy.sband_2g.sband); - mt7915_init_txpower_band(dev, &dev->mphy.sband_5g.sband); - - mt7915_eeprom_init_sku(dev); -} - static int mt7915_register_ext_phy(struct mt7915_dev *dev) { struct mt7915_phy *phy = mt7915_ext_phy(dev); @@ -238,22 +265,17 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev) phy->mt76 = mphy; mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1; - mt7915_init_wiphy(mphy->hw); INIT_LIST_HEAD(&phy->stats_list); INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work); mt7915_eeprom_parse_band_config(phy); - mt7915_set_stream_vht_txbf_caps(phy); - mt7915_set_stream_he_caps(phy); + mt7915_init_wiphy(mphy->hw); 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) @@ -278,9 +300,48 @@ static void mt7915_init_work(struct work_struct *work) mt7915_mcu_set_eeprom(dev); mt7915_mac_init(dev); - mt7915_init_txpower(dev); + 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 void mt7915_wfsys_reset(struct mt7915_dev *dev) +{ + u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; + +#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) +#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) + + mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM); + + /* change to software control */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* reset wfsys */ + val &= ~MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* release wfsys then mcu re-excutes romcode */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* switch to hw control */ + val &= ~MT_TOP_PWR_SW_RST; + val |= MT_TOP_PWR_HW_CTRL; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* check whether mcu resets to default */ + if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT, + MT_MCU_DUMMY_DEFAULT, 1000)) { + dev_err(dev->mt76.dev, "wifi subsystem reset failure\n"); + return; + } + + /* wfsys reset won't clear host registers */ + mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE); + + msleep(100); } static int mt7915_init_hardware(struct mt7915_dev *dev) @@ -290,10 +351,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); INIT_WORK(&dev->init_work, mt7915_init_work); - spin_lock_init(&dev->token_lock); - idr_init(&dev->token); + dev->dbdc_support = !!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)); - dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); + /* If MCU was already running, it is likely in a bad state */ + if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) > + FW_STATE_FW_DOWNLOAD) + mt7915_wfsys_reset(dev); ret = mt7915_dma_init(dev); if (ret) @@ -308,13 +371,26 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); ret = mt7915_mcu_init(dev); - if (ret) - return ret; + if (ret) { + /* Reset and try again */ + mt7915_wfsys_reset(dev); + + ret = mt7915_mcu_init(dev); + if (ret) + return ret; + } ret = mt7915_eeprom_init(dev); if (ret < 0) return ret; + + if (dev->flash_mode) { + ret = mt7915_mcu_apply_group_cal(dev); + if (ret) + return ret; + } + /* Beacon and mgmt frames should occupy wcid 0 */ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1); if (idx) @@ -330,8 +406,14 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy) { - int nss = hweight8(phy->mt76->chainmask); - u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap; + int nss; + u32 *cap; + + if (!phy->mt76->cap.has_5ghz) + return; + + nss = hweight8(phy->mt76->chainmask); + cap = &phy->mt76->sband_5g.sband.vht_cap.cap; *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | @@ -370,8 +452,8 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK; elem->phy_cap_info[5] &= ~c; - c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | - IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB; + c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | + IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] &= ~c; elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK; @@ -408,8 +490,8 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, c = (nss - 1) | (max_t(int, le16_to_cpu(mcs->tx_mcs_160), 1) << 3); elem->phy_cap_info[5] |= c; - c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | - IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB; + c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | + IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] |= c; /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ @@ -476,9 +558,9 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, IEEE80211_HE_MAC_CAP0_HTC_HE; he_cap_elem->mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL | - IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_RESERVED; + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3; he_cap_elem->mac_cap_info[4] = - IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU; + IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; if (band == NL80211_BAND_2GHZ) he_cap_elem->phy_cap_info[0] = @@ -535,7 +617,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; he_cap_elem->phy_cap_info[7] |= - IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR | + IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; he_cap_elem->phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | @@ -635,25 +717,14 @@ int mt7915_register_device(struct mt7915_dev *dev) return ret; mt7915_init_wiphy(hw); - dev->mphy.sband_2g.sband.ht_cap.cap |= - IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_MAX_AMSDU; - dev->mphy.sband_5g.sband.ht_cap.cap |= - IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_MAX_AMSDU; - dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + 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->mphy.chainmask; dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.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 @@ -667,6 +738,10 @@ int mt7915_register_device(struct mt7915_dev *dev) ieee80211_queue_work(mt76_hw(dev), &dev->init_work); + ret = mt7915_register_ext_phy(dev); + if (ret) + return ret; + return mt7915_init_debugfs(dev); } @@ -675,9 +750,8 @@ void mt7915_unregister_device(struct mt7915_dev *dev) mt7915_unregister_ext_phy(dev); mt76_unregister_device(&dev->mt76); mt7915_mcu_exit(dev); - mt7915_dma_cleanup(dev); - mt7915_tx_token_put(dev); + mt7915_dma_cleanup(dev); mt76_free_device(&dev->mt76); } |