mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-21 06:50:25 +00:00
wifi: mt76: mt7996: switch to single multi-radio wiphy
Use generic mt76 chanctx functions and look up phy from vif link. The driver now uses only a single phy to handle multiple interfaces on different channels. This is preparation for full MLO support. Link: https://patch.msgid.link/20250102163508.52945-23-nbd@nbd.name Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
1f8dd5686e
commit
69d54ce749
7 changed files with 597 additions and 383 deletions
|
@ -305,6 +305,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
|
||||||
|
|
||||||
mphy->antenna_mask = BIT(nss) - 1;
|
mphy->antenna_mask = BIT(nss) - 1;
|
||||||
mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
|
mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
|
||||||
|
phy->orig_chainmask = mphy->chainmask;
|
||||||
dev->chainmask |= mphy->chainmask;
|
dev->chainmask |= mphy->chainmask;
|
||||||
if (band_idx < MT_BAND2)
|
if (band_idx < MT_BAND2)
|
||||||
dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] +
|
dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] +
|
||||||
|
|
|
@ -14,6 +14,28 @@
|
||||||
#include "coredump.h"
|
#include "coredump.h"
|
||||||
#include "eeprom.h"
|
#include "eeprom.h"
|
||||||
|
|
||||||
|
static const struct ieee80211_iface_limit if_limits_global = {
|
||||||
|
.max = MT7996_MAX_INTERFACES * MT7996_MAX_RADIOS,
|
||||||
|
.types = BIT(NL80211_IFTYPE_STATION)
|
||||||
|
| BIT(NL80211_IFTYPE_ADHOC)
|
||||||
|
| BIT(NL80211_IFTYPE_AP)
|
||||||
|
#ifdef CONFIG_MAC80211_MESH
|
||||||
|
| BIT(NL80211_IFTYPE_MESH_POINT)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ieee80211_iface_combination if_comb_global = {
|
||||||
|
.limits = &if_limits_global,
|
||||||
|
.n_limits = 1,
|
||||||
|
.max_interfaces = MT7996_MAX_INTERFACES * MT7996_MAX_RADIOS,
|
||||||
|
.num_different_channels = MT7996_MAX_RADIOS,
|
||||||
|
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_20) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_40) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_80) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_160),
|
||||||
|
};
|
||||||
|
|
||||||
static const struct ieee80211_iface_limit if_limits[] = {
|
static const struct ieee80211_iface_limit if_limits[] = {
|
||||||
{
|
{
|
||||||
.max = 16,
|
.max = 16,
|
||||||
|
@ -27,8 +49,7 @@ static const struct ieee80211_iface_limit if_limits[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ieee80211_iface_combination if_comb[] = {
|
static const struct ieee80211_iface_combination if_comb = {
|
||||||
{
|
|
||||||
.limits = if_limits,
|
.limits = if_limits,
|
||||||
.n_limits = ARRAY_SIZE(if_limits),
|
.n_limits = ARRAY_SIZE(if_limits),
|
||||||
.max_interfaces = MT7996_MAX_INTERFACES,
|
.max_interfaces = MT7996_MAX_INTERFACES,
|
||||||
|
@ -40,7 +61,6 @@ static const struct ieee80211_iface_combination if_comb[] = {
|
||||||
BIT(NL80211_CHAN_WIDTH_80) |
|
BIT(NL80211_CHAN_WIDTH_80) |
|
||||||
BIT(NL80211_CHAN_WIDTH_160),
|
BIT(NL80211_CHAN_WIDTH_160),
|
||||||
.beacon_int_min_gcd = 100,
|
.beacon_int_min_gcd = 100,
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t mt7996_thermal_temp_show(struct device *dev,
|
static ssize_t mt7996_thermal_temp_show(struct device *dev,
|
||||||
|
@ -177,28 +197,32 @@ static const struct thermal_cooling_device_ops mt7996_thermal_ops = {
|
||||||
static void mt7996_unregister_thermal(struct mt7996_phy *phy)
|
static void mt7996_unregister_thermal(struct mt7996_phy *phy)
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||||
|
char name[sizeof("cooling_deviceXXX")];
|
||||||
|
|
||||||
if (!phy->cdev)
|
if (!phy->cdev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
|
snprintf(name, sizeof(name), "cooling_device%d", phy->mt76->band_idx);
|
||||||
|
sysfs_remove_link(&wiphy->dev.kobj, name);
|
||||||
thermal_cooling_device_unregister(phy->cdev);
|
thermal_cooling_device_unregister(phy->cdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt7996_thermal_init(struct mt7996_phy *phy)
|
static int mt7996_thermal_init(struct mt7996_phy *phy)
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||||
|
char cname[sizeof("cooling_deviceXXX")];
|
||||||
struct thermal_cooling_device *cdev;
|
struct thermal_cooling_device *cdev;
|
||||||
struct device *hwmon;
|
struct device *hwmon;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
|
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s.%d",
|
||||||
wiphy_name(wiphy));
|
wiphy_name(wiphy), phy->mt76->band_idx);
|
||||||
|
snprintf(cname, sizeof(cname), "cooling_device%d", phy->mt76->band_idx);
|
||||||
|
|
||||||
cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
|
cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
|
||||||
if (!IS_ERR(cdev)) {
|
if (!IS_ERR(cdev)) {
|
||||||
if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
|
if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
|
||||||
"cooling_device") < 0)
|
cname) < 0)
|
||||||
thermal_cooling_device_unregister(cdev);
|
thermal_cooling_device_unregister(cdev);
|
||||||
else
|
else
|
||||||
phy->cdev = cdev;
|
phy->cdev = cdev;
|
||||||
|
@ -330,27 +354,87 @@ mt7996_regd_notifier(struct wiphy *wiphy,
|
||||||
{
|
{
|
||||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
struct mt7996_phy *phy;
|
||||||
|
|
||||||
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
|
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
|
||||||
dev->mt76.region = request->dfs_region;
|
dev->mt76.region = request->dfs_region;
|
||||||
|
|
||||||
|
mt7996_for_each_phy(dev, phy) {
|
||||||
if (dev->mt76.region == NL80211_DFS_UNSET)
|
if (dev->mt76.region == NL80211_DFS_UNSET)
|
||||||
mt7996_mcu_rdd_background_enable(phy, NULL);
|
mt7996_mcu_rdd_background_enable(phy, NULL);
|
||||||
|
|
||||||
mt7996_init_txpower(phy);
|
mt7996_init_txpower(phy);
|
||||||
|
|
||||||
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
|
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
|
||||||
mt7996_dfs_init_radar_detector(phy);
|
mt7996_dfs_init_radar_detector(phy);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mt7996_init_wiphy_band(struct ieee80211_hw *hw, struct mt7996_phy *phy)
|
||||||
|
{
|
||||||
|
struct mt7996_dev *dev = phy->dev;
|
||||||
|
struct wiphy *wiphy = hw->wiphy;
|
||||||
|
int n_radios = hw->wiphy->n_radio;
|
||||||
|
struct wiphy_radio_freq_range *freq = &dev->radio_freqs[n_radios];
|
||||||
|
struct wiphy_radio *radio = &dev->radios[n_radios];
|
||||||
|
|
||||||
|
phy->slottime = 9;
|
||||||
|
phy->beacon_rate = -1;
|
||||||
|
|
||||||
|
if (phy->mt76->cap.has_2ghz) {
|
||||||
|
phy->mt76->sband_2g.sband.ht_cap.cap |=
|
||||||
|
IEEE80211_HT_CAP_LDPC_CODING |
|
||||||
|
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||||
|
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
||||||
|
IEEE80211_HT_MPDU_DENSITY_2;
|
||||||
|
freq->start_freq = 2400000;
|
||||||
|
freq->end_freq = 2500000;
|
||||||
|
} else 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_11454 |
|
||||||
|
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
|
||||||
|
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||||
|
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
||||||
|
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
||||||
|
IEEE80211_HT_MPDU_DENSITY_1;
|
||||||
|
|
||||||
|
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||||
|
freq->start_freq = 5000000;
|
||||||
|
freq->end_freq = 5900000;
|
||||||
|
} else if (phy->mt76->cap.has_6ghz) {
|
||||||
|
freq->start_freq = 5900000;
|
||||||
|
freq->end_freq = 7200000;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->radio_phy[n_radios] = phy;
|
||||||
|
radio->freq_range = freq;
|
||||||
|
radio->n_freq_range = 1;
|
||||||
|
radio->iface_combinations = &if_comb;
|
||||||
|
radio->n_iface_combinations = 1;
|
||||||
|
hw->wiphy->n_radio++;
|
||||||
|
|
||||||
|
wiphy->available_antennas_rx |= phy->mt76->chainmask;
|
||||||
|
wiphy->available_antennas_tx |= phy->mt76->chainmask;
|
||||||
|
|
||||||
|
mt76_set_stream_caps(phy->mt76, true);
|
||||||
|
mt7996_set_stream_vht_txbf_caps(phy);
|
||||||
|
mt7996_set_stream_he_eht_caps(phy);
|
||||||
|
mt7996_init_txpower(phy);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||||
{
|
{
|
||||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||||
struct mt76_dev *mdev = &phy->dev->mt76;
|
struct mt76_dev *mdev = &dev->mt76;
|
||||||
struct wiphy *wiphy = hw->wiphy;
|
struct wiphy *wiphy = hw->wiphy;
|
||||||
u16 max_subframes = phy->dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT :
|
u16 max_subframes = dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT :
|
||||||
IEEE80211_MAX_AMPDU_BUF_HE;
|
IEEE80211_MAX_AMPDU_BUF_HE;
|
||||||
|
|
||||||
hw->queues = 4;
|
hw->queues = 4;
|
||||||
|
@ -363,14 +447,15 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||||
hw->radiotap_timestamp.units_pos =
|
hw->radiotap_timestamp.units_pos =
|
||||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||||
|
|
||||||
phy->slottime = 9;
|
|
||||||
phy->beacon_rate = -1;
|
|
||||||
|
|
||||||
hw->sta_data_size = sizeof(struct mt7996_sta);
|
hw->sta_data_size = sizeof(struct mt7996_sta);
|
||||||
hw->vif_data_size = sizeof(struct mt7996_vif);
|
hw->vif_data_size = sizeof(struct mt7996_vif);
|
||||||
|
hw->chanctx_data_size = sizeof(struct mt76_chanctx);
|
||||||
|
|
||||||
|
wiphy->iface_combinations = &if_comb_global;
|
||||||
|
wiphy->n_iface_combinations = 1;
|
||||||
|
|
||||||
|
wiphy->radio = dev->radios;
|
||||||
|
|
||||||
wiphy->iface_combinations = if_comb;
|
|
||||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
|
||||||
wiphy->reg_notifier = mt7996_regd_notifier;
|
wiphy->reg_notifier = mt7996_regd_notifier;
|
||||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||||
wiphy->mbssid_max_interfaces = 16;
|
wiphy->mbssid_max_interfaces = 16;
|
||||||
|
@ -387,7 +472,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
|
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
|
||||||
|
|
||||||
if (mt7996_has_background_radar(phy->dev) &&
|
if (mt7996_has_background_radar(dev) &&
|
||||||
(!mdev->dev->of_node ||
|
(!mdev->dev->of_node ||
|
||||||
!of_property_read_bool(mdev->dev->of_node,
|
!of_property_read_bool(mdev->dev->of_node,
|
||||||
"mediatek,disable-radar-background")))
|
"mediatek,disable-radar-background")))
|
||||||
|
@ -397,51 +482,21 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||||
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
||||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
|
||||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||||
|
|
||||||
hw->max_tx_fragments = 4;
|
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;
|
|
||||||
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
|
||||||
IEEE80211_HT_MPDU_DENSITY_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_11454 |
|
|
||||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
|
|
||||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
|
||||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
|
||||||
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
|
||||||
IEEE80211_HT_MPDU_DENSITY_1;
|
|
||||||
|
|
||||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init led callbacks */
|
/* init led callbacks */
|
||||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||||
phy->mt76->leds.cdev.brightness_set = mt7996_led_set_brightness;
|
dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
|
||||||
phy->mt76->leds.cdev.blink_set = mt7996_led_set_blink;
|
dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink;
|
||||||
}
|
}
|
||||||
|
|
||||||
mt76_set_stream_caps(phy->mt76, true);
|
|
||||||
mt7996_set_stream_vht_txbf_caps(phy);
|
|
||||||
mt7996_set_stream_he_eht_caps(phy);
|
|
||||||
mt7996_init_txpower(phy);
|
|
||||||
|
|
||||||
wiphy->available_antennas_rx = phy->mt76->antenna_mask;
|
|
||||||
wiphy->available_antennas_tx = phy->mt76->antenna_mask;
|
|
||||||
|
|
||||||
wiphy->max_scan_ssids = 4;
|
wiphy->max_scan_ssids = 4;
|
||||||
wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
||||||
|
|
||||||
|
mt7996_init_wiphy_band(hw, &dev->phy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -562,18 +617,15 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
|
||||||
return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
|
return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
|
static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
|
||||||
enum mt76_band_id band)
|
|
||||||
{
|
{
|
||||||
|
struct mt7996_phy *phy;
|
||||||
struct mt76_phy *mphy;
|
struct mt76_phy *mphy;
|
||||||
u32 mac_ofs, hif1_ofs = 0;
|
u32 mac_ofs, hif1_ofs = 0;
|
||||||
int ret;
|
int ret;
|
||||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||||
|
|
||||||
if (!mt7996_band_valid(dev, band) || band == MT_BAND0)
|
if (!mt7996_band_valid(dev, band))
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (phy)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) {
|
if (is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) {
|
||||||
|
@ -581,7 +633,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
|
||||||
wed = &dev->mt76.mmio.wed_hif2;
|
wed = &dev->mt76.mmio.wed_hif2;
|
||||||
}
|
}
|
||||||
|
|
||||||
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band);
|
mphy = mt76_alloc_radio_phy(&dev->mt76, sizeof(*phy), band);
|
||||||
if (!mphy)
|
if (!mphy)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -612,7 +664,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
|
||||||
mt76_eeprom_override(mphy);
|
mt76_eeprom_override(mphy);
|
||||||
|
|
||||||
/* init wiphy according to mphy and phy */
|
/* init wiphy according to mphy and phy */
|
||||||
mt7996_init_wiphy(mphy->hw, wed);
|
mt7996_init_wiphy_band(mphy->hw, phy);
|
||||||
ret = mt7996_init_tx_queues(mphy->priv,
|
ret = mt7996_init_tx_queues(mphy->priv,
|
||||||
MT_TXQ_ID(band),
|
MT_TXQ_ID(band),
|
||||||
MT7996_TX_RING_SIZE,
|
MT7996_TX_RING_SIZE,
|
||||||
|
@ -626,10 +678,6 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ret = mt7996_thermal_init(phy);
|
|
||||||
if (ret)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
|
if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
|
||||||
u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;
|
u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;
|
||||||
|
|
||||||
|
@ -641,24 +689,14 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
|
||||||
|
|
||||||
error:
|
error:
|
||||||
mphy->dev->phys[band] = NULL;
|
mphy->dev->phys[band] = NULL;
|
||||||
ieee80211_free_hw(mphy->hw);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
|
mt7996_unregister_phy(struct mt7996_phy *phy)
|
||||||
{
|
{
|
||||||
struct mt76_phy *mphy;
|
if (phy)
|
||||||
|
|
||||||
if (!phy)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mt7996_unregister_thermal(phy);
|
mt7996_unregister_thermal(phy);
|
||||||
|
|
||||||
mphy = phy->dev->mt76.phys[band];
|
|
||||||
mt76_unregister_phy(mphy);
|
|
||||||
ieee80211_free_hw(mphy->hw);
|
|
||||||
phy->dev->mt76.phys[band] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mt7996_init_work(struct work_struct *work)
|
static void mt7996_init_work(struct work_struct *work)
|
||||||
|
@ -1412,6 +1450,7 @@ void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy)
|
||||||
int mt7996_register_device(struct mt7996_dev *dev)
|
int mt7996_register_device(struct mt7996_dev *dev)
|
||||||
{
|
{
|
||||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||||
|
struct mt7996_phy *phy;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev->phy.dev = dev;
|
dev->phy.dev = dev;
|
||||||
|
@ -1433,22 +1472,21 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
||||||
|
|
||||||
mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
|
mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
|
||||||
|
|
||||||
|
ret = mt7996_register_phy(dev, MT_BAND1);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = mt7996_register_phy(dev, MT_BAND2);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||||
ARRAY_SIZE(mt76_rates));
|
ARRAY_SIZE(mt76_rates));
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = mt7996_thermal_init(&dev->phy);
|
mt7996_for_each_phy(dev, phy)
|
||||||
if (ret)
|
mt7996_thermal_init(phy);
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = mt7996_register_phy(dev, mt7996_phy3(dev), MT_BAND2);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
|
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
|
||||||
|
|
||||||
|
@ -1473,8 +1511,8 @@ error:
|
||||||
void mt7996_unregister_device(struct mt7996_dev *dev)
|
void mt7996_unregister_device(struct mt7996_dev *dev)
|
||||||
{
|
{
|
||||||
cancel_work_sync(&dev->wed_rro.work);
|
cancel_work_sync(&dev->wed_rro.work);
|
||||||
mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
|
mt7996_unregister_phy(mt7996_phy3(dev));
|
||||||
mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
|
mt7996_unregister_phy(mt7996_phy2(dev));
|
||||||
mt7996_unregister_thermal(&dev->phy);
|
mt7996_unregister_thermal(&dev->phy);
|
||||||
mt7996_coredump_unregister(dev);
|
mt7996_coredump_unregister(dev);
|
||||||
mt76_unregister_device(&dev->mt76);
|
mt76_unregister_device(&dev->mt76);
|
||||||
|
|
|
@ -1738,19 +1738,19 @@ mt7996_mac_restart(struct mt7996_dev *dev)
|
||||||
ret = mt7996_txbf_init(dev);
|
ret = mt7996_txbf_init(dev);
|
||||||
|
|
||||||
if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
|
if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
|
||||||
ret = mt7996_run(dev->mphy.hw);
|
ret = mt7996_run(&dev->phy);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
|
if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
|
||||||
ret = mt7996_run(phy2->mt76->hw);
|
ret = mt7996_run(phy2);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
|
if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
|
||||||
ret = mt7996_run(phy3->mt76->hw);
|
ret = mt7996_run(phy3);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2572,18 +2572,24 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||||
#define OFFLOAD_TX_MODE_SU BIT(0)
|
#define OFFLOAD_TX_MODE_SU BIT(0)
|
||||||
#define OFFLOAD_TX_MODE_MU BIT(1)
|
#define OFFLOAD_TX_MODE_MU BIT(1)
|
||||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
|
||||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||||
struct cfg80211_chan_def *chandef = &mvif->deflink.phy->mt76->chandef;
|
struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
|
||||||
enum nl80211_band band = chandef->chan->band;
|
|
||||||
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
||||||
struct bss_inband_discovery_tlv *discov;
|
struct bss_inband_discovery_tlv *discov;
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
struct sk_buff *rskb, *skb = NULL;
|
struct sk_buff *rskb, *skb = NULL;
|
||||||
|
struct cfg80211_chan_def *chandef;
|
||||||
|
enum nl80211_band band;
|
||||||
struct tlv *tlv;
|
struct tlv *tlv;
|
||||||
u8 *buf, interval;
|
u8 *buf, interval;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
if (!phy)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
chandef = &phy->mt76->chandef;
|
||||||
|
band = chandef->chan->band;
|
||||||
|
|
||||||
if (vif->bss_conf.nontransmitted)
|
if (vif->bss_conf.nontransmitted)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -4495,7 +4501,6 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
|
||||||
#define TX_POWER_LIMIT_TABLE_RATE 0
|
#define TX_POWER_LIMIT_TABLE_RATE 0
|
||||||
struct mt7996_dev *dev = phy->dev;
|
struct mt7996_dev *dev = phy->dev;
|
||||||
struct mt76_phy *mphy = phy->mt76;
|
struct mt76_phy *mphy = phy->mt76;
|
||||||
struct ieee80211_hw *hw = mphy->hw;
|
|
||||||
struct tx_power_limit_table_ctrl {
|
struct tx_power_limit_table_ctrl {
|
||||||
u8 __rsv1[4];
|
u8 __rsv1[4];
|
||||||
|
|
||||||
|
@ -4515,7 +4520,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int i, tx_power;
|
int i, tx_power;
|
||||||
|
|
||||||
tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
|
tx_power = mt7996_get_power_bound(phy, phy->txpower);
|
||||||
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
|
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
|
||||||
&la, tx_power);
|
&la, tx_power);
|
||||||
mphy->txpower_cur = tx_power;
|
mphy->txpower_cur = tx_power;
|
||||||
|
|
|
@ -605,6 +605,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||||
static const struct mt76_driver_ops drv_ops = {
|
static const struct mt76_driver_ops drv_ops = {
|
||||||
/* txwi_size = txd size + txp size */
|
/* txwi_size = txd size + txp size */
|
||||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
|
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
|
||||||
|
.link_data_size = sizeof(struct mt7996_vif_link),
|
||||||
.drv_flags = MT_DRV_TXWI_NO_FREE |
|
.drv_flags = MT_DRV_TXWI_NO_FREE |
|
||||||
MT_DRV_AMSDU_OFFLOAD |
|
MT_DRV_AMSDU_OFFLOAD |
|
||||||
MT_DRV_HW_MGMT_TXQ,
|
MT_DRV_HW_MGMT_TXQ,
|
||||||
|
@ -622,6 +623,8 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||||
.sta_remove = mt7996_mac_sta_remove,
|
.sta_remove = mt7996_mac_sta_remove,
|
||||||
.update_survey = mt7996_update_channel,
|
.update_survey = mt7996_update_channel,
|
||||||
.set_channel = mt7996_set_channel,
|
.set_channel = mt7996_set_channel,
|
||||||
|
.vif_link_add = mt7996_vif_link_add,
|
||||||
|
.vif_link_remove = mt7996_vif_link_remove,
|
||||||
};
|
};
|
||||||
struct mt7996_dev *dev;
|
struct mt7996_dev *dev;
|
||||||
struct mt76_dev *mdev;
|
struct mt76_dev *mdev;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "../mt76_connac.h"
|
#include "../mt76_connac.h"
|
||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
|
|
||||||
|
#define MT7996_MAX_RADIOS 3
|
||||||
#define MT7996_MAX_INTERFACES 19 /* per-band */
|
#define MT7996_MAX_INTERFACES 19 /* per-band */
|
||||||
#define MT7996_MAX_WMM_SETS 4
|
#define MT7996_MAX_WMM_SETS 4
|
||||||
#define MT7996_WTBL_BMC_SIZE (is_mt7992(&dev->mt76) ? 32 : 64)
|
#define MT7996_WTBL_BMC_SIZE (is_mt7992(&dev->mt76) ? 32 : 64)
|
||||||
|
@ -270,11 +271,15 @@ struct mt7996_phy {
|
||||||
|
|
||||||
u32 rx_ampdu_ts;
|
u32 rx_ampdu_ts;
|
||||||
u32 ampdu_ref;
|
u32 ampdu_ref;
|
||||||
|
int txpower;
|
||||||
|
|
||||||
struct mt76_mib_stats mib;
|
struct mt76_mib_stats mib;
|
||||||
struct mt76_channel_state state_ts;
|
struct mt76_channel_state state_ts;
|
||||||
|
|
||||||
|
u16 orig_chainmask;
|
||||||
|
|
||||||
bool has_aux_rx;
|
bool has_aux_rx;
|
||||||
|
bool counter_reset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt7996_dev {
|
struct mt7996_dev {
|
||||||
|
@ -283,6 +288,10 @@ struct mt7996_dev {
|
||||||
struct mt76_phy mphy;
|
struct mt76_phy mphy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mt7996_phy *radio_phy[MT7996_MAX_RADIOS];
|
||||||
|
struct wiphy_radio radios[MT7996_MAX_RADIOS];
|
||||||
|
struct wiphy_radio_freq_range radio_freqs[MT7996_MAX_RADIOS];
|
||||||
|
|
||||||
struct mt7996_hif *hif2;
|
struct mt7996_hif *hif2;
|
||||||
struct mt7996_reg_desc reg;
|
struct mt7996_reg_desc reg;
|
||||||
u8 q_id[MT7996_MAX_QUEUE];
|
u8 q_id[MT7996_MAX_QUEUE];
|
||||||
|
@ -402,14 +411,6 @@ enum mt7996_rdd_cmd {
|
||||||
RDD_IRQ_OFF,
|
RDD_IRQ_OFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct mt7996_phy *
|
|
||||||
mt7996_hw_phy(struct ieee80211_hw *hw)
|
|
||||||
{
|
|
||||||
struct mt76_phy *phy = hw->priv;
|
|
||||||
|
|
||||||
return phy->priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct mt7996_dev *
|
static inline struct mt7996_dev *
|
||||||
mt7996_hw_dev(struct ieee80211_hw *hw)
|
mt7996_hw_dev(struct ieee80211_hw *hw)
|
||||||
{
|
{
|
||||||
|
@ -469,12 +470,35 @@ mt7996_has_background_radar(struct mt7996_dev *dev)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct mt7996_phy *
|
||||||
|
mt7996_band_phy(struct mt7996_dev *dev, enum nl80211_band band)
|
||||||
|
{
|
||||||
|
struct mt76_phy *mphy;
|
||||||
|
|
||||||
|
mphy = dev->mt76.band_phys[band];
|
||||||
|
if (!mphy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return mphy->priv;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct mt7996_vif_link *
|
static inline struct mt7996_vif_link *
|
||||||
mt7996_vif_link(struct mt7996_dev *dev, struct ieee80211_vif *vif, int link_id)
|
mt7996_vif_link(struct mt7996_dev *dev, struct ieee80211_vif *vif, int link_id)
|
||||||
{
|
{
|
||||||
return (struct mt7996_vif_link *)mt76_vif_link(&dev->mt76, vif, link_id);
|
return (struct mt7996_vif_link *)mt76_vif_link(&dev->mt76, vif, link_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct mt7996_phy *
|
||||||
|
mt7996_vif_link_phy(struct mt7996_vif_link *link)
|
||||||
|
{
|
||||||
|
struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76);
|
||||||
|
|
||||||
|
if (!mphy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return mphy->priv;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct mt7996_vif_link *
|
static inline struct mt7996_vif_link *
|
||||||
mt7996_vif_conf_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
mt7996_vif_conf_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_bss_conf *link_conf)
|
struct ieee80211_bss_conf *link_conf)
|
||||||
|
@ -483,6 +507,10 @@ mt7996_vif_conf_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||||
link_conf);
|
link_conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define mt7996_for_each_phy(dev, phy) \
|
||||||
|
for (int __i = 0; __i < ARRAY_SIZE((dev)->radio_phy); __i++) \
|
||||||
|
if (((phy) = (dev)->radio_phy[__i]) != NULL)
|
||||||
|
|
||||||
extern const struct ieee80211_ops mt7996_ops;
|
extern const struct ieee80211_ops mt7996_ops;
|
||||||
extern struct pci_driver mt7996_pci_driver;
|
extern struct pci_driver mt7996_pci_driver;
|
||||||
extern struct pci_driver mt7996_hif_driver;
|
extern struct pci_driver mt7996_hif_driver;
|
||||||
|
@ -494,6 +522,12 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
|
||||||
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
|
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
|
||||||
int mt7996_register_device(struct mt7996_dev *dev);
|
int mt7996_register_device(struct mt7996_dev *dev);
|
||||||
void mt7996_unregister_device(struct mt7996_dev *dev);
|
void mt7996_unregister_device(struct mt7996_dev *dev);
|
||||||
|
int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_bss_conf *link_conf,
|
||||||
|
struct mt76_vif_link *mlink);
|
||||||
|
void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_bss_conf *link_conf,
|
||||||
|
struct mt76_vif_link *mlink);
|
||||||
int mt7996_eeprom_init(struct mt7996_dev *dev);
|
int mt7996_eeprom_init(struct mt7996_dev *dev);
|
||||||
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
|
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
|
||||||
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
|
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
|
||||||
|
@ -509,7 +543,7 @@ int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx,
|
||||||
void mt7996_init_txpower(struct mt7996_phy *phy);
|
void mt7996_init_txpower(struct mt7996_phy *phy);
|
||||||
int mt7996_txbf_init(struct mt7996_dev *dev);
|
int mt7996_txbf_init(struct mt7996_dev *dev);
|
||||||
void mt7996_reset(struct mt7996_dev *dev);
|
void mt7996_reset(struct mt7996_dev *dev);
|
||||||
int mt7996_run(struct ieee80211_hw *hw);
|
int mt7996_run(struct mt7996_phy *phy);
|
||||||
int mt7996_mcu_init(struct mt7996_dev *dev);
|
int mt7996_mcu_init(struct mt7996_dev *dev);
|
||||||
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
|
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
|
||||||
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
||||||
|
|
Loading…
Add table
Reference in a new issue