mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
mt76: introduce single-sku support for mt7663/mt7921
Introduce support for rate-txpower compensation for mt7663/mt7921 chipsets. Rate-txpower limit is specified through dts Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
729d3dbd3b
commit
18369a4f9d
|
|
@ -323,8 +323,11 @@ mt7615_regd_notifier(struct wiphy *wiphy,
|
|||
|
||||
if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
|
||||
mt7615_dfs_init_radar_detector(phy);
|
||||
if (mt7615_firmware_offload(phy->dev))
|
||||
|
||||
if (mt7615_firmware_offload(phy->dev)) {
|
||||
mt76_connac_mcu_set_channel_domain(mphy);
|
||||
mt76_connac_mcu_set_rate_txpower(mphy);
|
||||
}
|
||||
|
||||
mt7615_mutex_release(dev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ static int mt7615_start(struct ieee80211_hw *hw)
|
|||
ret = mt76_connac_mcu_set_channel_domain(phy->mt76);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt76_connac_mcu_set_rate_txpower(phy->mt76);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
|
||||
|
|
|
|||
|
|
@ -1560,6 +1560,139 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);
|
||||
|
||||
static void
|
||||
mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
|
||||
struct mt76_power_limits *limits,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
int max_power = is_mt7921(dev) ? 127 : 63;
|
||||
int i, offset = sizeof(limits->cck);
|
||||
|
||||
memset(sku, max_power, MT_SKU_POWER_LIMIT);
|
||||
|
||||
if (band == NL80211_BAND_2GHZ) {
|
||||
/* cck */
|
||||
memcpy(sku, limits->cck, sizeof(limits->cck));
|
||||
}
|
||||
|
||||
/* ofdm */
|
||||
memcpy(&sku[offset], limits->ofdm, sizeof(limits->ofdm));
|
||||
offset += sizeof(limits->ofdm);
|
||||
|
||||
/* ht */
|
||||
for (i = 0; i < 2; i++) {
|
||||
memcpy(&sku[offset], limits->mcs[i], 8);
|
||||
offset += 8;
|
||||
}
|
||||
sku[offset++] = limits->mcs[0][0];
|
||||
|
||||
/* vht */
|
||||
for (i = 0; i < ARRAY_SIZE(limits->mcs); i++) {
|
||||
memcpy(&sku[offset], limits->mcs[i],
|
||||
ARRAY_SIZE(limits->mcs[i]));
|
||||
offset += 12;
|
||||
}
|
||||
|
||||
if (!is_mt7921(dev))
|
||||
return;
|
||||
|
||||
/* he */
|
||||
for (i = 0; i < ARRAY_SIZE(limits->ru); i++) {
|
||||
memcpy(&sku[offset], limits->ru[i], ARRAY_SIZE(limits->ru[i]));
|
||||
offset += ARRAY_SIZE(limits->ru[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
int sku_len, batch_len = is_mt7921(dev) ? 8 : 16;
|
||||
static const u8 chan_list_2ghz[] = {
|
||||
1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14
|
||||
};
|
||||
static const u8 chan_list_5ghz[] = {
|
||||
36, 38, 40, 42, 44, 46, 48,
|
||||
50, 52, 54, 56, 58, 60, 62,
|
||||
64, 100, 102, 104, 106, 108, 110,
|
||||
112, 114, 116, 118, 120, 122, 124,
|
||||
126, 128, 132, 134, 136, 138, 140,
|
||||
142, 144, 149, 151, 153, 155, 157,
|
||||
159, 161, 165
|
||||
};
|
||||
struct mt76_connac_sku_tlv sku_tlbv;
|
||||
int i, n_chan, batch_size, idx = 0;
|
||||
struct mt76_power_limits limits;
|
||||
const u8 *ch_list;
|
||||
|
||||
sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ) {
|
||||
n_chan = ARRAY_SIZE(chan_list_2ghz);
|
||||
ch_list = chan_list_2ghz;
|
||||
} else {
|
||||
n_chan = ARRAY_SIZE(chan_list_5ghz);
|
||||
ch_list = chan_list_5ghz;
|
||||
}
|
||||
batch_size = DIV_ROUND_UP(n_chan, batch_len);
|
||||
|
||||
for (i = 0; i < batch_size; i++) {
|
||||
bool last_msg = i == batch_size - 1;
|
||||
int num_ch = last_msg ? n_chan % batch_len : batch_len;
|
||||
struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {
|
||||
.band = band == NL80211_BAND_2GHZ ? 1 : 2,
|
||||
.n_chan = num_ch,
|
||||
.last_msg = last_msg,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
int j, err, msg_len;
|
||||
|
||||
msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
|
||||
skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(tx_power_tlv.alpha2));
|
||||
memcpy(tx_power_tlv.alpha2, dev->alpha2, sizeof(dev->alpha2));
|
||||
|
||||
skb_put_data(skb, &tx_power_tlv, sizeof(tx_power_tlv));
|
||||
for (j = 0; j < num_ch; j++, idx++) {
|
||||
struct ieee80211_channel chan = {
|
||||
.hw_value = ch_list[idx],
|
||||
.band = band,
|
||||
};
|
||||
|
||||
mt76_get_rate_power_limits(phy, &chan, &limits, 127);
|
||||
|
||||
sku_tlbv.channel = ch_list[idx];
|
||||
mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,
|
||||
&limits, band);
|
||||
skb_put_data(skb, &sku_tlbv, sku_len);
|
||||
}
|
||||
|
||||
err = mt76_mcu_skb_send_msg(dev, skb,
|
||||
MCU_CMD_SET_RATE_TX_POWER, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_2GHZ);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_5GHZ);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
const struct wiphy_wowlan_support mt76_connac_wowlan_support = {
|
||||
|
|
|
|||
|
|
@ -895,6 +895,28 @@ struct mt76_sta_cmd_info {
|
|||
u8 rcpi;
|
||||
};
|
||||
|
||||
#define MT_SKU_POWER_LIMIT 161
|
||||
|
||||
struct mt76_connac_sku_tlv {
|
||||
u8 channel;
|
||||
s8 pwr_limit[MT_SKU_POWER_LIMIT];
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_tx_power_limit_tlv {
|
||||
/* DW0 - common info*/
|
||||
u8 ver;
|
||||
u8 pad0;
|
||||
__le16 len;
|
||||
/* DW1 - cmd hint */
|
||||
u8 n_chan; /* # channel */
|
||||
u8 band; /* 2.4GHz - 5GHz */
|
||||
u8 last_msg;
|
||||
u8 pad1;
|
||||
/* DW3 */
|
||||
u8 alpha2[4]; /* regulatory_request.alpha2 */
|
||||
u8 pad2[32];
|
||||
} __packed;
|
||||
|
||||
#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
|
||||
#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
|
||||
|
||||
|
|
@ -996,4 +1018,5 @@ void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
|
|||
int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
|
||||
void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct mt76_connac_coredump *coredump);
|
||||
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy);
|
||||
#endif /* __MT76_CONNAC_MCU_H */
|
||||
|
|
|
|||
|
|
@ -58,12 +58,14 @@ mt7921_regd_notifier(struct wiphy *wiphy,
|
|||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
|
||||
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
|
||||
dev->mt76.region = request->dfs_region;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt76_connac_mcu_set_channel_domain(hw->priv);
|
||||
mt76_connac_mcu_set_rate_txpower(phy->mt76);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,10 @@ int __mt7921_start(struct mt7921_phy *phy)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt76_connac_mcu_set_rate_txpower(phy->mt76);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt7921_mac_reset_counters(phy);
|
||||
set_bit(MT76_STATE_RUNNING, &mphy->state);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user