mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
mt76 patches for 7.2
- fixes - mt792x broken usb transport detection - mt7921 regd improvements - mt7927 support -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCaifuiwAKCRDXfRQdAqdu 9Z+9AJ0R8q18QJa5sjra78OkI69Atc0VDwCeLxv3XyOyDzUWyq6ZEmPlpBRylc0= =+QHv -----END PGP SIGNATURE----- Merge tag 'mt76-next-2026-06-09' of https://github.com/nbd168/wireless Felix Fietkau says: =================== mt76 patches for 7.2 - fixes - mt792x broken usb transport detection - mt7921 regd improvements - mt7927 support =================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
0ccb7c3bb1
|
|
@ -307,7 +307,7 @@ void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
|
||||
rcu_assign_pointer(mvif->offchannel_link, NULL);
|
||||
dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink);
|
||||
kfree(mlink);
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
}
|
||||
|
||||
void mt76_roc_complete(struct mt76_phy *phy)
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ mt76_eeprom_override(struct mt76_phy *phy)
|
|||
if (err == -EPROBE_DEFER)
|
||||
return err;
|
||||
|
||||
if (!is_valid_ether_addr(phy->macaddr)) {
|
||||
if (err) {
|
||||
eth_random_addr(phy->macaddr);
|
||||
dev_info(dev->dev,
|
||||
"Invalid MAC address, using random address %pM\n",
|
||||
|
|
|
|||
|
|
@ -449,6 +449,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
|||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL);
|
||||
|
||||
if (!wiphy->max_remain_on_channel_duration)
|
||||
wiphy->max_remain_on_channel_duration = 5000;
|
||||
if (!wiphy->available_antennas_tx)
|
||||
wiphy->available_antennas_tx = phy->antenna_mask;
|
||||
if (!wiphy->available_antennas_rx)
|
||||
|
|
@ -1321,7 +1323,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
|
|||
* All further fragments will be validated by mac80211 only.
|
||||
*/
|
||||
if (ieee80211_is_frag(hdr) &&
|
||||
!ieee80211_is_first_frag(hdr->frame_control))
|
||||
!ieee80211_is_first_frag(hdr->seq_ctrl))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1576,6 +1578,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
{
|
||||
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt76_wcid *published;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
|
@ -1595,11 +1598,19 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
mtxq->wcid = wcid->idx;
|
||||
}
|
||||
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
||||
published = rcu_dereference_protected(dev->wcid[wcid->idx],
|
||||
lockdep_is_held(&dev->mutex));
|
||||
if (published != wcid) {
|
||||
WARN_ON_ONCE(published);
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
||||
mt76_wcid_init(wcid, phy->band_idx);
|
||||
} else {
|
||||
wcid->phy_idx = phy->band_idx;
|
||||
}
|
||||
|
||||
phy->num_sta++;
|
||||
|
||||
mt76_wcid_init(wcid, phy->band_idx);
|
||||
out:
|
||||
mutex_unlock(&dev->mutex);
|
||||
|
||||
|
|
|
|||
|
|
@ -361,6 +361,7 @@ enum mt76_wcid_flags {
|
|||
MT_WCID_FLAG_PS,
|
||||
MT_WCID_FLAG_4ADDR,
|
||||
MT_WCID_FLAG_HDR_TRANS,
|
||||
MT_WCID_FLAG_TDLS_PEER,
|
||||
};
|
||||
|
||||
#define MT76_N_WCIDS 1088
|
||||
|
|
|
|||
|
|
@ -550,8 +550,6 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
|
|||
struct dentry *dir;
|
||||
|
||||
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
if (is_mt7615(&dev->mt76))
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
|
||||
|
|
|
|||
|
|
@ -195,7 +195,6 @@ mt7615_check_offload_capability(struct mt7615_dev *dev)
|
|||
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
|
||||
|
||||
wiphy->flags &= ~WIPHY_FLAG_4ADDR_STATION;
|
||||
wiphy->max_remain_on_channel_duration = 5000;
|
||||
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
|
||||
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
|||
return -ENOMEM;
|
||||
|
||||
dev = container_of(mdev, struct mt7615_dev, mt76);
|
||||
udev = usb_get_dev(udev);
|
||||
usb_reset_device(udev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
|
@ -193,7 +192,6 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
|||
error:
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
|
|
@ -211,7 +209,6 @@ static void mt7663u_disconnect(struct usb_interface *usb_intf)
|
|||
mt7663u_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,11 +172,26 @@ struct mt76_connac_tx_free {
|
|||
|
||||
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
|
||||
|
||||
static inline bool is_connac3(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7925 || mt76_chip(dev) == 0x7927;
|
||||
}
|
||||
|
||||
static inline bool is_mt7925(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7925;
|
||||
}
|
||||
|
||||
static inline bool is_mt7927(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7927;
|
||||
}
|
||||
|
||||
static inline bool is_320mhz_supported(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7927;
|
||||
}
|
||||
|
||||
static inline bool is_mt7920(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7920;
|
||||
|
|
@ -279,6 +294,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
|
|||
case 0x7922:
|
||||
case 0x7902:
|
||||
case 0x7925:
|
||||
case 0x7927:
|
||||
case 0x7663:
|
||||
case 0x7622:
|
||||
return false;
|
||||
|
|
@ -420,7 +436,10 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
|
|||
void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss, enum nl80211_band band);
|
||||
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
||||
int ring_base, void *wed, u32 flags);
|
||||
|
||||
void mt76_connac_set_txpower_cur(struct mt76_phy *phy, s8 max_power);
|
||||
s8 mt76_connac_get_rate_power_limit(struct mt76_phy *phy,
|
||||
struct ieee80211_channel *chan,
|
||||
struct mt76_power_limits *limits);
|
||||
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
||||
struct mt76_tx_info *tx_info,
|
||||
void *txp_ptr, u32 id);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
|||
|
||||
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
|
||||
|
||||
if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
|
||||
if (is_mt7663(dev) || is_connac2(dev) || is_connac3(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_AMSDU_LAST |
|
||||
|
|
@ -217,7 +217,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev,
|
|||
u32 last_mask;
|
||||
int i;
|
||||
|
||||
if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
|
||||
if (is_mt7663(dev) || is_connac2(dev) || is_connac3(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_MSDU_LAST;
|
||||
|
|
@ -275,6 +275,15 @@ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues);
|
||||
|
||||
void mt76_connac_set_txpower_cur(struct mt76_phy *phy, s8 max_power)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = mt76_tx_power_path_delta(hweight16(phy->chainmask));
|
||||
phy->txpower_cur = max_power - delta;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_set_txpower_cur);
|
||||
|
||||
#define __bitrate_mask_check(_mcs, _mode) \
|
||||
({ \
|
||||
u8 i = 0; \
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
|
|||
|
||||
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
|
||||
(is_connac2(dev) && addr == 0x900000) ||
|
||||
(is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
|
||||
(is_connac3(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
|
||||
(is_mt799x(dev) && addr == 0x900000))
|
||||
cmd = MCU_CMD(PATCH_START_REQ);
|
||||
else
|
||||
|
|
@ -491,6 +491,11 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
|
|||
htr->to_ds = true;
|
||||
htr->from_ds = true;
|
||||
}
|
||||
|
||||
if (test_bit(MT_WCID_FLAG_TDLS_PEER, &wcid->flags)) {
|
||||
htr->to_ds = false;
|
||||
htr->from_ds = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);
|
||||
|
||||
|
|
@ -1227,6 +1232,9 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
|||
len = enable ? sizeof(dev_req) : sizeof(basic_req);
|
||||
|
||||
err = mt76_mcu_send_msg(dev, cmd, data, len, true);
|
||||
if (err && cmd == MCU_UNI_CMD(BSS_INFO_UPDATE))
|
||||
err = mt76_connac_mcu_bss_deact_err(dev, err, enable);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
@ -1234,7 +1242,11 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
|||
data = enable ? (void *)&basic_req : (void *)&dev_req;
|
||||
len = enable ? sizeof(basic_req) : sizeof(dev_req);
|
||||
|
||||
return mt76_mcu_send_msg(dev, cmd, data, len, true);
|
||||
err = mt76_mcu_send_msg(dev, cmd, data, len, true);
|
||||
if (err && cmd == MCU_UNI_CMD(BSS_INFO_UPDATE))
|
||||
err = mt76_connac_mcu_bss_deact_err(dev, err, enable);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_dev);
|
||||
|
||||
|
|
@ -2223,14 +2235,14 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
|||
.hw_value = ch_list[idx],
|
||||
.band = band,
|
||||
};
|
||||
s8 reg_power, sar_power;
|
||||
s8 max_power;
|
||||
|
||||
reg_power = mt76_connac_get_ch_power(phy, &chan,
|
||||
tx_power);
|
||||
sar_power = mt76_get_sar_power(phy, &chan, reg_power);
|
||||
|
||||
mt76_get_rate_power_limits(phy, &chan, limits,
|
||||
sar_power);
|
||||
max_power = mt76_connac_get_rate_power_limit(phy, &chan,
|
||||
limits);
|
||||
if (phy->chandef.chan &&
|
||||
phy->chandef.chan->hw_value == ch_list[idx] &&
|
||||
phy->chandef.chan->band == band)
|
||||
mt76_connac_set_txpower_cur(phy, max_power);
|
||||
|
||||
tx_power_tlv.last_msg = ch_list[idx] == last_ch;
|
||||
sku_tlbv.channel = ch_list[idx];
|
||||
|
|
@ -2962,6 +2974,23 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_rdd_cmd);
|
||||
|
||||
s8 mt76_connac_get_rate_power_limit(struct mt76_phy *phy,
|
||||
struct ieee80211_channel *chan,
|
||||
struct mt76_power_limits *limits)
|
||||
{
|
||||
s8 reg_power, sar_power;
|
||||
int tx_power;
|
||||
|
||||
tx_power = 2 * phy->hw->conf.power_level;
|
||||
if (!tx_power)
|
||||
tx_power = 127;
|
||||
|
||||
reg_power = mt76_connac_get_ch_power(phy, chan, tx_power);
|
||||
sar_power = mt76_get_sar_power(phy, chan, reg_power);
|
||||
return mt76_get_rate_power_limits(phy, chan, limits, sar_power);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_rate_power_limit);
|
||||
|
||||
static int
|
||||
mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev,
|
||||
const struct mt76_connac2_fw_trailer *hdr,
|
||||
|
|
@ -3084,7 +3113,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
|
|||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if ((!is_connac2(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
if ((!is_connac2(dev) && !is_connac3(dev)) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
|
|
|
|||
|
|
@ -1069,6 +1069,7 @@ enum {
|
|||
MCU_UNI_EVENT_SCAN_DONE = 0x0e,
|
||||
MCU_UNI_EVENT_RDD_REPORT = 0x11,
|
||||
MCU_UNI_EVENT_ROC = 0x27,
|
||||
MCU_UNI_EVENT_MBMC = 0x28,
|
||||
MCU_UNI_EVENT_TX_DONE = 0x2d,
|
||||
MCU_UNI_EVENT_THERMAL = 0x35,
|
||||
MCU_UNI_EVENT_RSSI_MONITOR = 0x41,
|
||||
|
|
@ -1598,7 +1599,7 @@ struct mt76_connac_hw_scan_done {
|
|||
u8 pno_enabled;
|
||||
u8 pad2[3];
|
||||
u8 sparse_channel_valid_num;
|
||||
u8 pad3[3];
|
||||
u8 alpha2[3];
|
||||
u8 channel_num[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
|
||||
/* idle format for channel_idle_time
|
||||
* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms)
|
||||
|
|
@ -1611,6 +1612,7 @@ struct mt76_connac_hw_scan_done {
|
|||
u8 mdrdy_count[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
|
||||
__le32 beacon_2g_num;
|
||||
__le32 beacon_5g_num;
|
||||
__le16 channel_scan_time[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_sched_scan_req {
|
||||
|
|
@ -1878,7 +1880,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa)
|
|||
|
||||
ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?
|
||||
DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0;
|
||||
if (is_connac2(dev) || is_mt7925(dev))
|
||||
if (is_connac2(dev) || is_connac3(dev))
|
||||
ret |= feature_set & FW_FEATURE_ENCRY_MODE ?
|
||||
DL_CONFIG_ENCRY_MODE_SEL : 0;
|
||||
ret |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
|
|
@ -1906,6 +1908,29 @@ mt76_connac_mcu_get_wlan_idx(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||
}
|
||||
}
|
||||
|
||||
#define MT76_CONNAC_MCU_STATUS_WLAN_FAILURE 0xc0000001
|
||||
|
||||
static inline int
|
||||
mt76_connac_mcu_bss_deact_err(struct mt76_dev *mdev, int err, bool enable)
|
||||
{
|
||||
if (err != (int)MT76_CONNAC_MCU_STATUS_WLAN_FAILURE)
|
||||
return err;
|
||||
|
||||
/* Ignore wlan_failure state false alarm when deactivating an
|
||||
* inactive network. It does not harm the firmware state.
|
||||
*/
|
||||
if (!enable) {
|
||||
dev_dbg(mdev->dev,
|
||||
"ignore wlan_failure when bss is deactivated\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_warn(mdev->dev,
|
||||
"wlan_failure when bss is activated\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
struct sk_buff *
|
||||
__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
||||
struct mt76_wcid *wcid, int len);
|
||||
|
|
|
|||
|
|
@ -245,7 +245,6 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
|||
if (id->driver_info)
|
||||
dev->no_2ghz = true;
|
||||
|
||||
usb_dev = usb_get_dev(usb_dev);
|
||||
usb_reset_device(usb_dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
|
@ -284,7 +283,6 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
|||
|
||||
err:
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
|
|
@ -303,7 +301,6 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf)
|
|||
mt76x0u_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ static const struct usb_device_id mt76x2u_device_table[] = {
|
|||
{ USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */
|
||||
{ USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
|
||||
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
|
||||
{ USB_DEVICE(0x056e, 0x400a) }, /* ELECOM WDC-867SU3S */
|
||||
{ USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */
|
||||
{ USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */
|
||||
{ USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
|
||||
|
|
@ -57,7 +58,6 @@ static int mt76x2u_probe(struct usb_interface *intf,
|
|||
|
||||
dev = container_of(mdev, struct mt76x02_dev, mt76);
|
||||
|
||||
udev = usb_get_dev(udev);
|
||||
usb_reset_device(udev);
|
||||
|
||||
usb_set_intfdata(intf, dev);
|
||||
|
|
@ -84,14 +84,12 @@ static int mt76x2u_probe(struct usb_interface *intf,
|
|||
mt76u_queues_deinit(&dev->mt76);
|
||||
mt76_free_device(&dev->mt76);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
usb_put_dev(udev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mt76x2u_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct mt76x02_dev *dev = usb_get_intfdata(intf);
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
|
||||
|
|
@ -100,7 +98,6 @@ static void mt76x2u_disconnect(struct usb_interface *intf)
|
|||
mt76x2u_cleanup(dev);
|
||||
mt76_free_device(&dev->mt76);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
usb_put_dev(udev);
|
||||
}
|
||||
|
||||
static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf,
|
||||
|
|
|
|||
|
|
@ -1296,8 +1296,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
|
|||
struct dentry *dir;
|
||||
|
||||
dir = mt76_register_debugfs_fops(phy->mt76, NULL);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
debugfs_create_file("muru_debug", 0600, dir, dev, &fops_muru_debug);
|
||||
debugfs_create_file("muru_stats", 0400, dir, phy,
|
||||
&mt7915_muru_stats_fops);
|
||||
|
|
|
|||
|
|
@ -912,16 +912,16 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
|||
}
|
||||
|
||||
if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) {
|
||||
u32 tx_retries = 0, tx_failed = 0;
|
||||
u32 tx_retries = 0, tx_failed = 0, count;
|
||||
|
||||
if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) {
|
||||
tx_retries =
|
||||
FIELD_GET(MT_TX_FREE_COUNT_V3, info) - 1;
|
||||
count = FIELD_GET(MT_TX_FREE_COUNT_V3, info);
|
||||
tx_retries = count ? count - 1 : 0;
|
||||
tx_failed = tx_retries +
|
||||
!!FIELD_GET(MT_TX_FREE_STAT_V3, info);
|
||||
} else if (!v3 && (info & MT_TX_FREE_MPDU_HEADER)) {
|
||||
tx_retries =
|
||||
FIELD_GET(MT_TX_FREE_COUNT, info) - 1;
|
||||
count = FIELD_GET(MT_TX_FREE_COUNT, info);
|
||||
tx_retries = count ? count - 1 : 0;
|
||||
tx_failed = tx_retries +
|
||||
!!FIELD_GET(MT_TX_FREE_STAT, info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -760,6 +760,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
msta->wcid.phy_idx = ext_phy;
|
||||
msta->jiffies = jiffies;
|
||||
|
||||
if (sta->tdls)
|
||||
set_bit(MT_WCID_FLAG_TDLS_PEER, &msta->wcid.flags);
|
||||
|
||||
ewma_avg_signal_init(&msta->avg_ack_signal);
|
||||
|
||||
mt7915_mac_wtbl_update(dev, idx,
|
||||
|
|
|
|||
|
|
@ -3534,10 +3534,18 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len,
|
|||
if (category == TX_POWER_INFO_RATE) {
|
||||
s8 res[MT7915_SKU_RATE_NUM][2];
|
||||
|
||||
if (skb->len < sizeof(res) + 4) {
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(res, skb->data + 4, sizeof(res));
|
||||
for (i = 0; i < len; i++)
|
||||
txpower[i] = res[i][req.band_idx];
|
||||
} else if (category == TX_POWER_INFO_PATH) {
|
||||
if (skb->len < len + 4) {
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(txpower, skb->data + 4, len);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ obj-$(CONFIG_MT7921E) += mt7921e.o
|
|||
obj-$(CONFIG_MT7921S) += mt7921s.o
|
||||
obj-$(CONFIG_MT7921U) += mt7921u.o
|
||||
|
||||
mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o
|
||||
mt7921-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o
|
||||
mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
mt7921e-y := pci.o pci_mac.o pci_mcu.o
|
||||
mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o
|
||||
|
|
|
|||
|
|
@ -266,8 +266,6 @@ int mt7921_init_debugfs(struct mt792x_dev *dev)
|
|||
struct dentry *dir;
|
||||
|
||||
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mt76_is_mmio(&dev->mt76))
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "mt7921.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "mcu.h"
|
||||
#include "regd.h"
|
||||
|
||||
static ssize_t mt7921_thermal_temp_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
|
@ -60,103 +61,6 @@ static int mt7921_thermal_init(struct mt792x_phy *phy)
|
|||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
|
||||
{
|
||||
#define IS_UNII_INVALID(idx, sfreq, efreq) \
|
||||
(!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct device_node *np, *band_np;
|
||||
struct ieee80211_channel *ch;
|
||||
int i, cfreq;
|
||||
|
||||
np = mt76_find_power_limits_node(mdev);
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_5GHZ];
|
||||
band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
cfreq = ch->center_freq;
|
||||
|
||||
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* UNII-4 */
|
||||
if (IS_UNII_INVALID(0, 5845, 5925))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_6GHZ];
|
||||
if (!sband)
|
||||
return;
|
||||
|
||||
band_np = np ? of_get_child_by_name(np, "txpower-6g") : NULL;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
cfreq = ch->center_freq;
|
||||
|
||||
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* UNII-5/6/7/8 */
|
||||
if (IS_UNII_INVALID(1, 5925, 6425) ||
|
||||
IS_UNII_INVALID(2, 6425, 6525) ||
|
||||
IS_UNII_INVALID(3, 6525, 6875) ||
|
||||
IS_UNII_INVALID(4, 6875, 7125))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
void mt7921_regd_update(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct ieee80211_hw *hw = mdev->hw;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
|
||||
mt7921_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env);
|
||||
mt7921_regd_channel_update(wiphy, dev);
|
||||
mt76_connac_mcu_set_channel_domain(hw->priv);
|
||||
mt7921_set_tx_sar_pwr(hw, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_regd_update);
|
||||
|
||||
static void
|
||||
mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
|
||||
dev->mt76.region = request->dfs_region;
|
||||
dev->country_ie_env = request->country_ie_env;
|
||||
|
||||
if (request->initiator == NL80211_REGDOM_SET_BY_USER) {
|
||||
if (dev->mt76.alpha2[0] == '0' && dev->mt76.alpha2[1] == '0')
|
||||
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
|
||||
else
|
||||
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
|
||||
}
|
||||
|
||||
if (pm->suspended)
|
||||
return;
|
||||
|
||||
dev->regd_in_progress = true;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt7921_regd_update(dev);
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
dev->regd_in_progress = false;
|
||||
wake_up(&dev->wait);
|
||||
}
|
||||
|
||||
int mt7921_mac_init(struct mt792x_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "mt7921.h"
|
||||
#include "../dma.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "regd.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
|
||||
|
|
@ -530,8 +531,9 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
|
|||
stat = FIELD_GET(MT_TX_FREE_STATUS, info);
|
||||
|
||||
if (wcid) {
|
||||
wcid->stats.tx_retries +=
|
||||
FIELD_GET(MT_TX_FREE_COUNT, info) - 1;
|
||||
u32 count = FIELD_GET(MT_TX_FREE_COUNT, info);
|
||||
|
||||
wcid->stats.tx_retries += count ? count - 1 : 0;
|
||||
wcid->stats.tx_failed += !!stat;
|
||||
}
|
||||
|
||||
|
|
@ -675,7 +677,9 @@ void mt7921_mac_reset_work(struct work_struct *work)
|
|||
if (!ret)
|
||||
break;
|
||||
}
|
||||
if (mt76_is_sdio(&dev->mt76) && atomic_read(&dev->mt76.bus_hung))
|
||||
|
||||
if ((mt76_is_sdio(&dev->mt76) || mt76_is_usb(&dev->mt76)) &&
|
||||
atomic_read(&dev->mt76.bus_hung))
|
||||
return;
|
||||
|
||||
if (i == 10)
|
||||
|
|
@ -697,6 +701,8 @@ void mt7921_mac_reset_work(struct work_struct *work)
|
|||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_vif_connect_iter, NULL);
|
||||
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
|
||||
|
||||
mt7921_regd_change(&dev->phy, "00");
|
||||
}
|
||||
|
||||
void mt7921_coredump_work(struct work_struct *work)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <net/ipv6.h>
|
||||
#include "mt7921.h"
|
||||
#include "regd.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static int
|
||||
|
|
@ -801,7 +802,7 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add)
|
|||
|
||||
out:
|
||||
if (vif->bss_conf.chanreq.oper.chan->band == NL80211_BAND_6GHZ)
|
||||
mt7921_regd_update(dev);
|
||||
mt7921_mcu_regd_update(dev, dev->mt76.alpha2, dev->country_ie_env);
|
||||
}
|
||||
|
||||
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
|
|
@ -828,6 +829,9 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
msta->deflink.last_txs = jiffies;
|
||||
msta->deflink.sta = msta;
|
||||
|
||||
if (sta->tdls)
|
||||
set_bit(MT_WCID_FLAG_TDLS_PEER, &msta->deflink.wcid.flags);
|
||||
|
||||
ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1027,8 +1031,16 @@ void mt7921_scan_work(struct work_struct *work)
|
|||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
if (rxd->eid == MCU_EVENT_SCHED_SCAN_DONE) {
|
||||
ieee80211_sched_scan_results(phy->mt76->hw);
|
||||
} else if (test_and_clear_bit(MT76_HW_SCANNING,
|
||||
&phy->mt76->state)) {
|
||||
} else if (rxd->eid == MCU_EVENT_SCAN_DONE) {
|
||||
struct mt76_connac_hw_scan_done *event = NULL;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
event = (struct mt76_connac_hw_scan_done *)skb->data;
|
||||
mt7921_regd_change(phy, event->alpha2);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(MT76_HW_SCANNING,
|
||||
&phy->mt76->state)) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
|
@ -1405,10 +1417,12 @@ mt7921_change_chanctx(struct ieee80211_hw *hw,
|
|||
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
|
||||
|
||||
mt792x_mutex_acquire(phy->dev);
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR)
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
||||
mt7921_mcu_set_sniffer(mvif->phy->dev, vif, true);
|
||||
mt7921_mcu_config_sniffer(mvif, ctx);
|
||||
else
|
||||
} else {
|
||||
mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx);
|
||||
}
|
||||
mt792x_mutex_release(phy->dev);
|
||||
}
|
||||
|
||||
|
|
@ -1508,6 +1522,9 @@ static void mt7921_channel_switch_rx_beacon(struct ieee80211_hw *hw,
|
|||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
u16 beacon_interval = vif->bss_conf.beacon_int;
|
||||
|
||||
if (!dev->new_ctx)
|
||||
return;
|
||||
|
||||
if (cfg80211_chandef_identical(&chsw->chandef,
|
||||
&dev->new_ctx->def) &&
|
||||
chsw->count) {
|
||||
|
|
@ -1552,7 +1569,7 @@ const struct ieee80211_ops mt7921_ops = {
|
|||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
.release_buffered_frames = mt76_release_buffered_frames,
|
||||
.channel_switch_beacon = mt7921_channel_switch_beacon,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
.get_txpower = mt792x_get_txpower,
|
||||
.get_stats = mt792x_get_stats,
|
||||
.get_et_sset_count = mt792x_get_et_sset_count,
|
||||
.get_et_strings = mt792x_get_et_strings,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "mt7921.h"
|
||||
#include "regd.h"
|
||||
#include "mcu.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "../mt792x_trace.h"
|
||||
|
|
@ -11,10 +12,6 @@
|
|||
#define MT_STA_BFER BIT(0)
|
||||
#define MT_STA_BFEE BIT(1)
|
||||
|
||||
static bool mt7921_disable_clc;
|
||||
module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_clc, "disable CLC support");
|
||||
|
||||
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
struct sk_buff *skb, int seq)
|
||||
{
|
||||
|
|
@ -422,8 +419,8 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
|||
u8 *clc_base = NULL, hw_encap = 0;
|
||||
|
||||
dev->phy.clc_chan_conf = 0xff;
|
||||
if (mt7921_disable_clc ||
|
||||
mt76_is_usb(&dev->mt76))
|
||||
dev->regd_user = false;
|
||||
if (!mt7921_regd_clc_supported(dev))
|
||||
return 0;
|
||||
|
||||
if (mt76_is_mmio(&dev->mt76)) {
|
||||
|
|
@ -488,7 +485,8 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
ret = mt7921_mcu_set_clc(dev, "00", ENVIRON_INDOOR);
|
||||
|
||||
ret = mt7921_regd_init(phy);
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
|
|
|
|||
|
|
@ -260,7 +260,6 @@ mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val)
|
|||
#define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
|
||||
#define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0)
|
||||
|
||||
void mt7921_regd_update(struct mt792x_dev *dev);
|
||||
int mt7921_mac_init(struct mt792x_dev *dev);
|
||||
bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask);
|
||||
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "../mt76_connac2_mac.h"
|
||||
#include "../dma.h"
|
||||
#include "mcu.h"
|
||||
#include "regd.h"
|
||||
|
||||
static const struct pci_device_id mt7921_pci_device_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961),
|
||||
|
|
@ -343,11 +344,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
pci_set_drvdata(pdev, mdev);
|
||||
|
||||
regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
|
||||
regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
|
||||
if (IS_ERR(regs)) {
|
||||
ret = PTR_ERR(regs);
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &mt7921_pcie_ops;
|
||||
dev->irq_map = &irq_map;
|
||||
|
|
@ -359,8 +363,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
/* MT7902 needs a mutable copy because wm2_complete_mask differs */
|
||||
map = devm_kmemdup(&pdev->dev, &irq_map,
|
||||
sizeof(irq_map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
if (!map) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
map->rx.wm2_complete_mask = 0;
|
||||
dev->irq_map = map;
|
||||
|
|
@ -583,7 +589,7 @@ static int mt7921_pci_resume(struct device *device)
|
|||
if (err < 0)
|
||||
goto failed;
|
||||
|
||||
mt7921_regd_update(dev);
|
||||
mt7921_mcu_regd_update(dev, mdev->alpha2, dev->country_ie_env);
|
||||
err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_ON_LED);
|
||||
failed:
|
||||
pm->suspended = false;
|
||||
|
|
|
|||
206
drivers/net/wireless/mediatek/mt76/mt7921/regd.c
Normal file
206
drivers/net/wireless/mediatek/mt76/mt7921/regd.c
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/* Copyright (C) 2025 MediaTek Inc. */
|
||||
|
||||
#include <linux/of.h>
|
||||
#include "mt7921.h"
|
||||
#include "regd.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static bool mt7921_disable_clc;
|
||||
module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_clc, "disable CLC support");
|
||||
|
||||
bool mt7921_regd_clc_supported(struct mt792x_dev *dev)
|
||||
{
|
||||
if (mt7921_disable_clc ||
|
||||
mt76_is_usb(&dev->mt76))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
|
||||
{
|
||||
#define IS_UNII_INVALID(idx, sfreq, efreq) \
|
||||
(!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct device_node *np, *band_np;
|
||||
struct ieee80211_channel *ch;
|
||||
int i, cfreq;
|
||||
|
||||
np = mt76_find_power_limits_node(mdev);
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_5GHZ];
|
||||
band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
cfreq = ch->center_freq;
|
||||
|
||||
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* UNII-4 */
|
||||
if (IS_UNII_INVALID(0, 5845, 5925))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_6GHZ];
|
||||
if (!sband)
|
||||
return;
|
||||
|
||||
band_np = np ? of_get_child_by_name(np, "txpower-6g") : NULL;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
cfreq = ch->center_freq;
|
||||
|
||||
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* UNII-5/6/7/8 */
|
||||
if (IS_UNII_INVALID(1, 5925, 6425) ||
|
||||
IS_UNII_INVALID(2, 6425, 6525) ||
|
||||
IS_UNII_INVALID(3, 6525, 6875) ||
|
||||
IS_UNII_INVALID(4, 6875, 7125))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
|
||||
enum environment_cap country_ie_env)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct ieee80211_hw *hw = mdev->hw;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
int ret = 0;
|
||||
|
||||
dev->regd_in_progress = true;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
if (!dev->regd_change)
|
||||
goto err;
|
||||
|
||||
ret = mt7921_mcu_set_clc(dev, alpha2, country_ie_env);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
mt7921_regd_channel_update(wiphy, dev);
|
||||
|
||||
ret = mt76_connac_mcu_set_channel_domain(hw->priv);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = mt7921_set_tx_sar_pwr(hw, NULL);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
err:
|
||||
mt792x_mutex_release(dev);
|
||||
dev->regd_change = false;
|
||||
dev->regd_in_progress = false;
|
||||
wake_up(&dev->wait);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mcu_regd_update);
|
||||
|
||||
void mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *req)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
|
||||
if (req->initiator == NL80211_REGDOM_SET_BY_USER &&
|
||||
!dev->regd_user)
|
||||
dev->regd_user = true;
|
||||
|
||||
/* do not need to update the same country twice */
|
||||
if (!memcmp(req->alpha2, mdev->alpha2, 2) &&
|
||||
dev->country_ie_env == req->country_ie_env)
|
||||
return;
|
||||
|
||||
memcpy(mdev->alpha2, req->alpha2, 2);
|
||||
mdev->region = req->dfs_region;
|
||||
dev->country_ie_env = req->country_ie_env;
|
||||
|
||||
if (req->initiator == NL80211_REGDOM_SET_BY_USER) {
|
||||
if (dev->mt76.alpha2[0] == '0' && dev->mt76.alpha2[1] == '0')
|
||||
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
|
||||
else
|
||||
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
|
||||
}
|
||||
|
||||
dev->regd_change = true;
|
||||
|
||||
if (pm->suspended)
|
||||
return;
|
||||
|
||||
mt7921_mcu_regd_update(dev, req->alpha2,
|
||||
req->country_ie_env);
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7921_regd_is_valid_alpha2(const char *alpha2)
|
||||
{
|
||||
if (!alpha2)
|
||||
return false;
|
||||
|
||||
if (alpha2[0] == '0' && alpha2[1] == '0')
|
||||
return true;
|
||||
|
||||
if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int mt7921_regd_change(struct mt792x_phy *phy, char *alpha2)
|
||||
{
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
|
||||
if (dev->hw_full_reset)
|
||||
return 0;
|
||||
|
||||
if (!mt7921_regd_is_valid_alpha2(alpha2) ||
|
||||
!mt7921_regd_clc_supported(dev) ||
|
||||
dev->regd_user)
|
||||
return -EINVAL;
|
||||
|
||||
if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
|
||||
return 0;
|
||||
|
||||
/* do not need to update the same country twice */
|
||||
if (!memcmp(alpha2, mdev->alpha2, 2))
|
||||
return 0;
|
||||
|
||||
if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
|
||||
return regulatory_hint(wiphy, alpha2);
|
||||
else
|
||||
return mt7921_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR);
|
||||
}
|
||||
|
||||
int mt7921_regd_init(struct mt792x_phy *phy)
|
||||
{
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
|
||||
if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
|
||||
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE |
|
||||
REGULATORY_DISABLE_BEACON_HINTS;
|
||||
else
|
||||
memzero_explicit(&mdev->alpha2, sizeof(mdev->alpha2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
drivers/net/wireless/mediatek/mt76/mt7921/regd.h
Normal file
19
drivers/net/wireless/mediatek/mt76/mt7921/regd.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/* Copyright (C) 2025 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7921_REGD_H
|
||||
#define __MT7921_REGD_H
|
||||
|
||||
struct mt792x_dev;
|
||||
struct wiphy;
|
||||
struct regulatory_request;
|
||||
|
||||
int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
|
||||
enum environment_cap country_ie_env);
|
||||
void mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request);
|
||||
bool mt7921_regd_clc_supported(struct mt792x_dev *dev);
|
||||
int mt7921_regd_change(struct mt792x_phy *phy, char *alpha2);
|
||||
int mt7921_regd_init(struct mt792x_phy *phy);
|
||||
|
||||
#endif
|
||||
|
|
@ -13,6 +13,8 @@
|
|||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
static const struct usb_device_id mt7921u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7902, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7902_FIRMWARE_WM },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
/* Comfast CF-952AX */
|
||||
|
|
@ -88,6 +90,10 @@ static int mt7921u_mac_reset(struct mt792x_dev *dev)
|
|||
{
|
||||
int err;
|
||||
|
||||
mt792xu_reset_on_bus_error(dev);
|
||||
if (atomic_read(&dev->mt76.bus_hung))
|
||||
return 0;
|
||||
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
|
||||
|
|
@ -196,8 +202,9 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &hif_ops;
|
||||
atomic_set(&dev->mt76.bus_hung, false);
|
||||
mt792xu_reset_work_init(dev);
|
||||
|
||||
udev = usb_get_dev(udev);
|
||||
usb_reset_device(udev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
|
@ -244,9 +251,9 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
|
||||
error:
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
mt792xu_reset_work_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
|
|
|
|||
|
|
@ -291,8 +291,6 @@ int mt7925_init_debugfs(struct mt792x_dev *dev)
|
|||
struct dentry *dir;
|
||||
|
||||
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mt76_is_mmio(&dev->mt76))
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
|
|
|
|||
|
|
@ -117,6 +117,15 @@ static int __mt7925_init_hardware(struct mt792x_dev *dev)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
ret = mt7925_mcu_set_dbdc(&dev->mphy, true);
|
||||
if (ret) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"MT7927 DBDC enable failed: %d\n", ret);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -232,7 +241,8 @@ int mt7925_register_device(struct mt792x_dev *dev)
|
|||
dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
|
||||
dev->pm.stats.last_wake_event = jiffies;
|
||||
dev->pm.stats.last_doze_event = jiffies;
|
||||
if (!mt76_is_usb(&dev->mt76)) {
|
||||
/* MT7927: runtime PM crashes BT firmware on the shared CONNINFRA domain */
|
||||
if (!mt76_is_usb(&dev->mt76) && !is_mt7927(&dev->mt76)) {
|
||||
dev->pm.enable_user = true;
|
||||
dev->pm.enable = true;
|
||||
dev->pm.ds_enable_user = true;
|
||||
|
|
|
|||
|
|
@ -339,6 +339,11 @@ mt7925_mac_fill_rx_rate(struct mt792x_dev *dev,
|
|||
case IEEE80211_STA_RX_BW_160:
|
||||
status->bw = RATE_INFO_BW_160;
|
||||
break;
|
||||
/* RXV can report 320 in two positions */
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
case IEEE80211_STA_RX_BW_320 + 1:
|
||||
status->bw = RATE_INFO_BW_320;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -841,7 +846,6 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,
|
|||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_sta *msta;
|
||||
bool is_8023;
|
||||
u16 fc, tid;
|
||||
|
|
@ -880,14 +884,14 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,
|
|||
|
||||
msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
|
||||
if (sta->mlo && msta->deflink_id != IEEE80211_LINK_UNSPECIFIED)
|
||||
mlink = rcu_dereference(msta->link[msta->deflink_id]);
|
||||
else
|
||||
mlink = &msta->deflink;
|
||||
|
||||
if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state)) {
|
||||
/* Packets belonging to the same TID can be transmitted over multiple
|
||||
* links. Keep the TX BA session state in the primary link so all links
|
||||
* share the same AMPDU bookkeeping.
|
||||
*/
|
||||
if (!test_and_set_bit(tid, &msta->deflink.wcid.ampdu_state)) {
|
||||
if (ieee80211_start_tx_ba_session(sta, tid, 0))
|
||||
clear_bit(tid, &mlink->wcid.ampdu_state);
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -997,6 +1001,10 @@ mt7925_mac_add_txs_skb(struct mt792x_dev *dev, struct mt76_wcid *wcid,
|
|||
stats->tx_mode[mode]++;
|
||||
|
||||
switch (FIELD_GET(MT_TXS0_BW, txs)) {
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
rate.bw = RATE_INFO_BW_320;
|
||||
stats->tx_bw[4]++;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
rate.bw = RATE_INFO_BW_160;
|
||||
stats->tx_bw[3]++;
|
||||
|
|
@ -1141,8 +1149,9 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
|
|||
|
||||
if (info & MT_TXFREE_INFO_HEADER) {
|
||||
if (wcid) {
|
||||
wcid->stats.tx_retries +=
|
||||
FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
|
||||
u32 count = FIELD_GET(MT_TXFREE_INFO_COUNT, info);
|
||||
|
||||
wcid->stats.tx_retries += count ? count - 1 : 0;
|
||||
wcid->stats.tx_failed +=
|
||||
!!FIELD_GET(MT_TXFREE_INFO_STAT, info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,6 +183,10 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
|||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
|
||||
|
||||
if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76))
|
||||
eht_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
|
||||
|
||||
eht_cap_elem->phy_cap_info[0] |=
|
||||
u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
|
||||
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
|
||||
|
|
@ -193,10 +197,20 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
|||
u8_encode_bits(sts - 1,
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK);
|
||||
|
||||
if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76))
|
||||
eht_cap_elem->phy_cap_info[1] |=
|
||||
u8_encode_bits(sts - 1,
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[2] =
|
||||
u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK);
|
||||
|
||||
if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76))
|
||||
eht_cap_elem->phy_cap_info[2] |=
|
||||
u8_encode_bits(sts - 1,
|
||||
IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[3] =
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
|
||||
|
|
@ -217,7 +231,8 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
|||
u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)),
|
||||
IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK);
|
||||
|
||||
val = width == NL80211_CHAN_WIDTH_160 ? 0x7 :
|
||||
val = width == NL80211_CHAN_WIDTH_320 ? 0xf :
|
||||
width == NL80211_CHAN_WIDTH_160 ? 0x7 :
|
||||
width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1;
|
||||
eht_cap_elem->phy_cap_info[6] =
|
||||
u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)),
|
||||
|
|
@ -239,6 +254,11 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
|||
eht_nss->bw._160.rx_tx_mcs9_max_nss = val;
|
||||
eht_nss->bw._160.rx_tx_mcs11_max_nss = val;
|
||||
eht_nss->bw._160.rx_tx_mcs13_max_nss = val;
|
||||
if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76)) {
|
||||
eht_nss->bw._320.rx_tx_mcs9_max_nss = val;
|
||||
eht_nss->bw._320.rx_tx_mcs11_max_nss = val;
|
||||
eht_nss->bw._320.rx_tx_mcs13_max_nss = val;
|
||||
}
|
||||
}
|
||||
|
||||
int mt7925_init_mlo_caps(struct mt792x_phy *phy)
|
||||
|
|
@ -376,6 +396,18 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
|||
mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ?
|
||||
0 : mconf->mt76.idx;
|
||||
mconf->mt76.band_idx = 0xff;
|
||||
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
if (link_conf->chanreq.oper.chan)
|
||||
chan = link_conf->chanreq.oper.chan;
|
||||
else
|
||||
chan = mvif->phy->mt76->chandef.chan;
|
||||
|
||||
mconf->mt76.band_idx = mt7927_band_idx(chan->band);
|
||||
}
|
||||
|
||||
mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?
|
||||
0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
|
||||
mconf->mt76.link_idx = hweight16(mvif->valid_links);
|
||||
|
|
@ -887,6 +919,9 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
|||
mlink->wcid.link_valid = !!link_sta->sta->valid_links;
|
||||
mlink->sta = msta;
|
||||
|
||||
if (link_sta->sta->tdls)
|
||||
set_bit(MT_WCID_FLAG_TDLS_PEER, &mlink->wcid.flags);
|
||||
|
||||
wcid = &mlink->wcid;
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);
|
||||
|
|
@ -1265,6 +1300,9 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
|||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
break;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && sta->tdls)
|
||||
continue;
|
||||
|
||||
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
|
||||
if (!link_sta)
|
||||
continue;
|
||||
|
|
@ -1318,14 +1356,14 @@ void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
unsigned long rem;
|
||||
|
||||
rem = ieee80211_vif_is_mld(vif) ? msta->valid_links : BIT(0);
|
||||
|
||||
mt7925_mac_sta_remove_links(dev, vif, sta, rem);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
mt7925_mac_sta_remove_links(dev, vif, sta, msta->valid_links);
|
||||
mt7925_mcu_del_dev(mdev, vif);
|
||||
} else {
|
||||
mt7925_mac_link_sta_remove(mdev, vif, &sta->deflink,
|
||||
&msta->deflink);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
mvif->wep_sta = NULL;
|
||||
|
|
@ -1372,22 +1410,22 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
case IEEE80211_AMPDU_RX_START:
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn,
|
||||
params->buf_size);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, true);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, vif, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, false);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, vif, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
mt7925_mcu_uni_tx_ba(dev, params, true);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, vif, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, false);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, vif, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
set_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
|
|
@ -1396,7 +1434,7 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, false);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, vif, false);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
|
|
@ -2179,9 +2217,9 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
rcu_assign_pointer(mvif->link_conf[link_id], NULL);
|
||||
rcu_assign_pointer(mvif->sta.link[link_id], NULL);
|
||||
|
||||
if (mconf != &mvif->bss_conf)
|
||||
if (mconfs[link_id] != &mvif->bss_conf)
|
||||
devm_kfree(dev->mt76.dev, mconfs[link_id]);
|
||||
if (mlink != &mvif->sta.deflink)
|
||||
if (mlinks[link_id] != &mvif->sta.deflink)
|
||||
devm_kfree(dev->mt76.dev, mlinks[link_id]);
|
||||
}
|
||||
|
||||
|
|
@ -2218,6 +2256,29 @@ mt7925_change_sta_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7927_reconfig_band(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt792x_bss_conf *mconf,
|
||||
u8 band_idx)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_link_sta *mlink = &mvif->sta.deflink;
|
||||
int ret;
|
||||
|
||||
ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf,
|
||||
&mconf->mt76, &mlink->wcid,
|
||||
false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mconf->mt76.band_idx = band_idx;
|
||||
|
||||
return mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf,
|
||||
&mconf->mt76, &mlink->wcid,
|
||||
true);
|
||||
}
|
||||
|
||||
static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
|
|
@ -2228,6 +2289,7 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct ieee80211_bss_conf *pri_link_conf;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
u8 band_idx;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
|
|
@ -2241,6 +2303,12 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
NULL, true);
|
||||
} else {
|
||||
mconf = &mvif->bss_conf;
|
||||
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
band_idx = mt7927_band_idx(ctx->def.chan->band);
|
||||
|
||||
mt7927_reconfig_band(dev, vif, link_conf, mconf, band_idx);
|
||||
}
|
||||
}
|
||||
|
||||
mconf->mt76.ctx = ctx;
|
||||
|
|
@ -2400,6 +2468,9 @@ static void mt7925_channel_switch_rx_beacon(struct ieee80211_hw *hw,
|
|||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
if (!dev->new_ctx)
|
||||
return;
|
||||
|
||||
beacon_interval = vif->bss_conf.beacon_int;
|
||||
|
||||
if (cfg80211_chandef_identical(&chsw->chandef,
|
||||
|
|
@ -2433,7 +2504,7 @@ const struct ieee80211_ops mt7925_ops = {
|
|||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
.release_buffered_frames = mt76_release_buffered_frames,
|
||||
.channel_switch_beacon = mt7925_channel_switch_beacon,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
.get_txpower = mt792x_get_txpower,
|
||||
.get_stats = mt792x_get_stats,
|
||||
.get_et_sset_count = mt792x_get_et_sset_count,
|
||||
.get_et_strings = mt792x_get_et_strings,
|
||||
|
|
|
|||
|
|
@ -566,6 +566,34 @@ mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mcu_handle_mbmc_event(struct mt792x_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mbmc_conf_tlv *tlv;
|
||||
u32 tlv_len;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4);
|
||||
tlv_len = skb->len;
|
||||
tlv = (struct mbmc_conf_tlv *)skb->data;
|
||||
|
||||
while (tlv_len >= sizeof(*tlv) &&
|
||||
le16_to_cpu(tlv->len) >= sizeof(*tlv) &&
|
||||
le16_to_cpu(tlv->len) <= tlv_len) {
|
||||
u16 tag = le16_to_cpu(tlv->tag);
|
||||
|
||||
if (tag == UNI_MBMC_SETTING || tag == UNI_MBMC_NO_RESP_SETTING) {
|
||||
dev_dbg(dev->mt76.dev,
|
||||
"MBMC event: tag=%u mbmc_en=%u\n",
|
||||
tag, tlv->mbmc_en);
|
||||
break;
|
||||
}
|
||||
|
||||
tlv_len -= le16_to_cpu(tlv->len);
|
||||
tlv = (struct mbmc_conf_tlv *)
|
||||
((u8 *)tlv + le16_to_cpu(tlv->len));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,
|
||||
struct sk_buff *skb)
|
||||
|
|
@ -584,6 +612,9 @@ mt7925_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,
|
|||
case MCU_UNI_EVENT_ROC:
|
||||
mt7925_mcu_uni_roc_event(dev, skb);
|
||||
break;
|
||||
case MCU_UNI_EVENT_MBMC:
|
||||
mt7925_mcu_handle_mbmc_event(dev, skb);
|
||||
break;
|
||||
case MCU_UNI_EVENT_SCAN_DONE:
|
||||
mt7925_mcu_scan_event(dev, skb);
|
||||
return;
|
||||
|
|
@ -624,9 +655,8 @@ void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
|
|||
static int
|
||||
mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable, bool tx)
|
||||
struct mt76_wcid *wcid, bool enable, bool tx)
|
||||
{
|
||||
struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
|
||||
struct sta_rec_ba_uni *ba;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
|
|
@ -652,30 +682,69 @@ mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
|||
MCU_UNI_CMD(STA_REC_UPDATE), true);
|
||||
}
|
||||
|
||||
/** starec & wtbl **/
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable)
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
unsigned int link_id;
|
||||
|
||||
if (enable && !params->amsdu)
|
||||
msta->deflink.wcid.amsdu = false;
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
int ret;
|
||||
|
||||
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
|
||||
enable, true);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
if (!mlink)
|
||||
return -EINVAL;
|
||||
|
||||
mconf = mt792x_vif_to_link(msta->vif, link_id);
|
||||
if (!mconf)
|
||||
return -EINVAL;
|
||||
|
||||
if (enable && !params->amsdu)
|
||||
mlink->wcid.amsdu = false;
|
||||
|
||||
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, params,
|
||||
&mlink->wcid, enable, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable)
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
unsigned int link_id;
|
||||
|
||||
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
|
||||
enable, false);
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
int ret;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
if (!mlink)
|
||||
return -EINVAL;
|
||||
|
||||
mconf = mt792x_vif_to_link(msta->vif, link_id);
|
||||
if (!mconf)
|
||||
return -EINVAL;
|
||||
|
||||
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, params,
|
||||
&mlink->wcid, enable, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)
|
||||
|
|
@ -1091,6 +1160,11 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
|
|||
hdr_trans->to_ds = true;
|
||||
hdr_trans->from_ds = true;
|
||||
}
|
||||
|
||||
if (test_bit(MT_WCID_FLAG_TDLS_PEER, &wcid->flags)) {
|
||||
hdr_trans->to_ds = false;
|
||||
hdr_trans->from_ds = false;
|
||||
}
|
||||
}
|
||||
|
||||
int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
|
||||
|
|
@ -1667,6 +1741,7 @@ mt7925_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)
|
|||
memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20));
|
||||
memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80));
|
||||
memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160));
|
||||
memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2334,6 +2409,10 @@ void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy,
|
|||
case NL80211_CHAN_WIDTH_160:
|
||||
req->bw = CMD_CBW_160MHZ;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_320:
|
||||
req->bw = CMD_CBW_320MHZ;
|
||||
req->center_chan2 = ieee80211_frequency_to_channel(freq2);
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
req->bw = CMD_CBW_5MHZ;
|
||||
break;
|
||||
|
|
@ -2827,6 +2906,7 @@ int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
|
|||
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
struct mt792x_dev *dev = phy->dev;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76,
|
||||
MT7925_BSS_UPDATE_MAX_SIZE);
|
||||
|
|
@ -2852,8 +2932,9 @@ int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
|
|||
mt7925_mcu_bss_mbssid_tlv(skb, link_conf, enable);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
err = mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
return mt76_connac_mcu_bss_deact_err(&dev->mt76, err, enable);
|
||||
}
|
||||
|
||||
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
|
|
@ -2911,6 +2992,7 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
|
|||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_set_dbdc);
|
||||
|
||||
static void
|
||||
mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
|
||||
|
|
|
|||
|
|
@ -143,7 +143,8 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
UNI_MBMC_SETTING,
|
||||
UNI_MBMC_SETTING = 0,
|
||||
UNI_MBMC_NO_RESP_SETTING = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,19 @@ enum mt7925_rxq_id {
|
|||
MT7925_RXQ_MCU_WM2, /* for tx done */
|
||||
};
|
||||
|
||||
enum mt7927_txq_id {
|
||||
MT7927_TXQ_BAND0 = MT7925_TXQ_BAND0,
|
||||
MT7927_TXQ_BAND1 = MT7925_TXQ_BAND1,
|
||||
MT7927_TXQ_MCU_WM = MT7925_TXQ_MCU_WM,
|
||||
MT7927_TXQ_FWDL = MT7925_TXQ_FWDL,
|
||||
};
|
||||
|
||||
enum mt7927_rxq_id {
|
||||
MT7927_RXQ_BAND0 = 4,
|
||||
MT7927_RXQ_MCU_WM = 6,
|
||||
MT7927_RXQ_DATA2 = 7,
|
||||
};
|
||||
|
||||
enum {
|
||||
MODE_OPEN = 0,
|
||||
MODE_SHARED = 1,
|
||||
|
|
@ -239,6 +252,18 @@ struct mt7925_txpwr {
|
|||
s8 eht996x3_484[16][2];
|
||||
};
|
||||
|
||||
static inline u8 mt7927_band_idx(enum nl80211_band band)
|
||||
{
|
||||
switch (band) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
return 0;
|
||||
case NL80211_BAND_5GHZ:
|
||||
case NL80211_BAND_6GHZ:
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
extern const struct ieee80211_ops mt7925_ops;
|
||||
|
||||
int __mt7925_start(struct mt792x_phy *phy);
|
||||
|
|
@ -293,10 +318,10 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
|
|||
bool enable);
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
void mt7925_mlo_pm_work(struct work_struct *work);
|
||||
void mt7925_scan_work(struct work_struct *work);
|
||||
void mt7925_roc_work(struct work_struct *work);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ static const struct pci_device_id mt7925_pci_device_table[] = {
|
|||
.driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0717),
|
||||
.driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7927),
|
||||
.driver_data = (kernel_ulong_t)MT7927_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x6639),
|
||||
.driver_data = (kernel_ulong_t)MT7927_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0738),
|
||||
.driver_data = (kernel_ulong_t)MT7927_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
@ -210,48 +216,55 @@ static u32 mt7925_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
|
|||
return dev->bus_ops->rmw(mdev, addr, mask, val);
|
||||
}
|
||||
|
||||
static int mt7925_dma_init(struct mt792x_dev *dev)
|
||||
static const struct mt792x_dma_layout mt7925_dma_layout = {
|
||||
.tx_data0 = mt792x_dma_ring(MT7925_TXQ_BAND0,
|
||||
MT7925_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE),
|
||||
.tx_mcu = mt792x_dma_ring(MT7925_TXQ_MCU_WM,
|
||||
MT7925_TX_MCU_RING_SIZE,
|
||||
MT_TX_RING_BASE),
|
||||
.tx_fwdl = mt792x_dma_ring(MT7925_TXQ_FWDL,
|
||||
MT7925_TX_FWDL_RING_SIZE,
|
||||
MT_TX_RING_BASE),
|
||||
.rx_mcu = mt792x_dma_ring(MT7925_RXQ_MCU_WM,
|
||||
MT7925_RX_MCU_RING_SIZE,
|
||||
MT_RX_EVENT_RING_BASE),
|
||||
.rx_data = mt792x_dma_ring(MT7925_RXQ_BAND0,
|
||||
MT7925_RX_RING_SIZE,
|
||||
MT_RX_DATA_RING_BASE),
|
||||
};
|
||||
|
||||
static const struct mt792x_dma_layout mt7927_dma_layout = {
|
||||
.tx_data0 = mt792x_dma_ring(MT7927_TXQ_BAND0,
|
||||
MT7925_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE),
|
||||
.tx_mcu = mt792x_dma_ring(MT7927_TXQ_MCU_WM,
|
||||
MT7925_TX_MCU_RING_SIZE,
|
||||
MT_TX_RING_BASE),
|
||||
.tx_fwdl = mt792x_dma_ring(MT7927_TXQ_FWDL,
|
||||
MT7925_TX_FWDL_RING_SIZE,
|
||||
MT_TX_RING_BASE),
|
||||
.rx_mcu = mt792x_dma_ring(MT7927_RXQ_MCU_WM,
|
||||
MT7925_RX_MCU_RING_SIZE,
|
||||
MT_RX_EVENT_RING_BASE),
|
||||
.rx_data = mt792x_dma_ring(MT7927_RXQ_BAND0,
|
||||
MT7925_RX_RING_SIZE,
|
||||
MT_RX_DATA_RING_BASE),
|
||||
};
|
||||
|
||||
static int mt7927_dma_init(struct mt792x_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mt76_dma_attach(&dev->mt76);
|
||||
|
||||
ret = mt792x_dma_disable(dev, true);
|
||||
ret = mt792x_dma_alloc_queues(dev, &mt7927_dma_layout);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* init tx queue */
|
||||
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7925_TXQ_BAND0,
|
||||
MT7925_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
|
||||
|
||||
/* command to WM */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7925_TXQ_MCU_WM,
|
||||
MT7925_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* firmware download */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7925_TXQ_FWDL,
|
||||
MT7925_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rx event */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
|
||||
MT7925_RXQ_MCU_WM, MT7925_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rx data */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
|
||||
MT7925_RXQ_BAND0, MT7925_RX_RING_SIZE,
|
||||
MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
|
||||
MT7927_RXQ_DATA2,
|
||||
MT7925_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT_RX_DATA_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -266,6 +279,37 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
|
|||
return mt792x_dma_enable(dev);
|
||||
}
|
||||
|
||||
static int mt7925_dma_init(struct mt792x_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt792x_dma_alloc_queues(dev, &mt7925_dma_layout);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_init_queues(dev, mt792x_poll_rx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt792x_poll_tx);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
return mt792x_dma_enable(dev);
|
||||
}
|
||||
|
||||
static const struct mt792x_irq_map mt7927_irq_map = {
|
||||
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
|
||||
.tx = {
|
||||
.all_complete_mask = MT_INT_TX_DONE_ALL,
|
||||
.mcu_complete_mask = MT_INT_TX_DONE_MCU,
|
||||
},
|
||||
.rx = {
|
||||
.data_complete_mask = MT7927_RX_DONE_INT_ENA4,
|
||||
.wm_complete_mask = MT7927_RX_DONE_INT_ENA6,
|
||||
.wm2_complete_mask = MT7927_RX_DONE_INT_ENA7,
|
||||
},
|
||||
};
|
||||
static int mt7925_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
|
|
@ -310,6 +354,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
|
|||
struct mt76_bus_ops *bus_ops;
|
||||
struct mt792x_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
bool is_mt7927_hw;
|
||||
u8 features;
|
||||
int ret;
|
||||
u16 cmd;
|
||||
|
|
@ -337,7 +382,11 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
|
|||
if (ret)
|
||||
goto err_free_pci_vec;
|
||||
|
||||
if (mt7925_disable_aspm)
|
||||
is_mt7927_hw = (pdev->device == 0x6639 || pdev->device == 0x7927 ||
|
||||
pdev->device == 0x0738);
|
||||
|
||||
/* MT7927: ASPM L1 causes unreliable WFDMA register access */
|
||||
if (mt7925_disable_aspm || is_mt7927_hw)
|
||||
mt76_pci_disable_aspm(pdev);
|
||||
|
||||
ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7925_ops,
|
||||
|
|
@ -358,7 +407,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
|
|||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &mt7925_pcie_ops;
|
||||
dev->irq_map = &irq_map;
|
||||
dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &irq_map;
|
||||
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
|
||||
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
|
||||
|
||||
|
|
@ -394,6 +443,13 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
if (is_mt7927_hw && mt76_chip(mdev) != 0x7927) {
|
||||
dev_info(mdev->dev,
|
||||
"MT7927 raw CHIPID=0x%04x, forcing chip=0x7927\n",
|
||||
mt76_chip(mdev));
|
||||
mdev->rev = (0x7927 << 16) | (mdev->rev & 0xff);
|
||||
}
|
||||
|
||||
mt76_rmw_field(dev, MT_HW_EMI_CTL, MT_HW_EMI_CTL_SLPPROT_EN, 1);
|
||||
|
||||
ret = mt792x_wfsys_reset(dev);
|
||||
|
|
@ -409,16 +465,24 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
|
|||
if (ret)
|
||||
goto err_free_dev;
|
||||
|
||||
ret = mt7925_dma_init(dev);
|
||||
if (is_mt7927(&dev->mt76))
|
||||
ret = mt7927_dma_init(dev);
|
||||
else if (is_mt7925(&dev->mt76))
|
||||
ret = mt7925_dma_init(dev);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
ret = mt7925_register_device(dev);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
goto err_free_dma;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_dma:
|
||||
mt792x_dma_cleanup(dev);
|
||||
err_free_irq:
|
||||
devm_free_irq(&pdev->dev, pdev->irq, dev);
|
||||
err_free_dev:
|
||||
|
|
@ -549,7 +613,10 @@ static int _mt7925_pci_resume(struct device *device, bool restore)
|
|||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt76_connac_irq_enable(&dev->mt76,
|
||||
dev->irq_map->tx.all_complete_mask |
|
||||
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
|
||||
dev->irq_map->rx.data_complete_mask |
|
||||
dev->irq_map->rx.wm_complete_mask |
|
||||
dev->irq_map->rx.wm2_complete_mask |
|
||||
MT_INT_MCU_CMD);
|
||||
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
|
||||
|
||||
/* put dma enabled */
|
||||
|
|
@ -633,6 +700,8 @@ module_pci_driver(mt7925_pci_driver);
|
|||
MODULE_DEVICE_TABLE(pci, mt7925_pci_device_table);
|
||||
MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7925_ROM_PATCH);
|
||||
MODULE_FIRMWARE(MT7927_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7927_ROM_PATCH);
|
||||
MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_DESCRIPTION("MediaTek MT7925E (PCIe) wireless driver");
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "mt7925.h"
|
||||
#include "../dma.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
int mt7925e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
|
|
@ -118,7 +119,10 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
|
|||
|
||||
mt76_wr(dev, dev->irq_map->host_irq_enable,
|
||||
dev->irq_map->tx.all_complete_mask |
|
||||
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
|
||||
dev->irq_map->rx.data_complete_mask |
|
||||
dev->irq_map->rx.wm_complete_mask |
|
||||
dev->irq_map->rx.wm2_complete_mask |
|
||||
MT_INT_MCU_CMD);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
|
||||
err = mt792xe_mcu_fw_pmctrl(dev);
|
||||
|
|
@ -141,6 +145,12 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
err = mt7925_mcu_set_dbdc(&dev->mphy, true);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = __mt7925_start(&dev->phy);
|
||||
out:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ mt7925_tm_query(struct mt792x_dev *dev, struct mt7925_tm_cmd *req,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (skb->len < MT7925_EVT_RSP_LEN + 8) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy((char *)evt_resp, (char *)skb->data + 8, MT7925_EVT_RSP_LEN);
|
||||
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -10,8 +10,13 @@
|
|||
#include "mac.h"
|
||||
|
||||
static const struct usb_device_id mt7925u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x6639, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7925, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
/* Netgear, Inc. A8500 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9050, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
/* Netgear, Inc. A9000 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9072, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
|
|
@ -120,6 +125,12 @@ static int mt7925u_mac_reset(struct mt792x_dev *dev)
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
err = mt7925_mcu_set_dbdc(&dev->mphy, true);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = __mt7925_start(&dev->phy);
|
||||
out:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
|
@ -184,8 +195,8 @@ static int mt7925u_probe(struct usb_interface *usb_intf,
|
|||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &hif_ops;
|
||||
mt792xu_reset_work_init(dev);
|
||||
|
||||
udev = usb_get_dev(udev);
|
||||
usb_reset_device(udev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
|
@ -198,6 +209,13 @@ static int mt7925u_probe(struct usb_interface *usb_intf,
|
|||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
if (mt76_chip(mdev) == 0x6639) {
|
||||
dev_dbg(mdev->dev,
|
||||
"MT7927 raw CHIPID=0x%04x, forcing chip=0x7927\n",
|
||||
mt76_chip(mdev));
|
||||
mdev->rev = (0x7927 << 16) | (mdev->rev & 0xff);
|
||||
}
|
||||
|
||||
if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
|
||||
ret = mt792xu_wfsys_reset(dev);
|
||||
if (ret)
|
||||
|
|
@ -232,9 +250,9 @@ static int mt7925u_probe(struct usb_interface *usb_intf,
|
|||
|
||||
error:
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
mt792xu_reset_work_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,12 +46,14 @@
|
|||
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
|
||||
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
|
||||
#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
|
||||
#define MT7927_FIRMWARE_WM "mediatek/mt7927/WIFI_RAM_CODE_MT6639_2_1.bin"
|
||||
|
||||
#define MT7902_ROM_PATCH "mediatek/WIFI_MT7902_patch_mcu_1_1_hdr.bin"
|
||||
#define MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"
|
||||
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
|
||||
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
|
||||
#define MT7925_ROM_PATCH "mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin"
|
||||
#define MT7927_ROM_PATCH "mediatek/mt7927/WIFI_MT6639_PATCH_MCU_2_1_hdr.bin"
|
||||
|
||||
#define MT792x_SDIO_HDR_TX_BYTES GENMASK(15, 0)
|
||||
#define MT792x_SDIO_HDR_PKT_TYPE GENMASK(17, 16)
|
||||
|
|
@ -204,6 +206,23 @@ struct mt792x_irq_map {
|
|||
} rx;
|
||||
};
|
||||
|
||||
struct mt792x_dma_ring {
|
||||
u8 qid;
|
||||
u16 n_desc;
|
||||
u32 ring_base;
|
||||
};
|
||||
|
||||
struct mt792x_dma_layout {
|
||||
struct mt792x_dma_ring tx_data0;
|
||||
struct mt792x_dma_ring tx_mcu;
|
||||
struct mt792x_dma_ring tx_fwdl;
|
||||
struct mt792x_dma_ring rx_data;
|
||||
struct mt792x_dma_ring rx_mcu;
|
||||
};
|
||||
|
||||
#define mt792x_dma_ring(_qid, _n_desc, _ring_base) \
|
||||
{ .qid = (_qid), .n_desc = (_n_desc), .ring_base = (_ring_base) }
|
||||
|
||||
#define mt792x_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
|
||||
#define mt792x_dev_reset(dev) ((dev)->hif_ops->reset(dev))
|
||||
#define mt792x_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev))
|
||||
|
|
@ -243,6 +262,8 @@ struct mt792x_dev {
|
|||
wait_queue_head_t wait;
|
||||
|
||||
struct work_struct init_work;
|
||||
struct work_struct usb_reset_work;
|
||||
atomic_t usb_reset_pending;
|
||||
|
||||
u8 fw_debug;
|
||||
u8 fw_features;
|
||||
|
|
@ -397,6 +418,8 @@ void mt792x_roc_timer(struct timer_list *timer);
|
|||
void mt792x_csa_timer(struct timer_list *timer);
|
||||
void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u32 queues, bool drop);
|
||||
int mt792x_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
unsigned int link_id, int *dbm);
|
||||
int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
|
|
@ -419,6 +442,8 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw,
|
|||
void mt792x_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
|
||||
s16 coverage_class);
|
||||
void mt792x_dma_cleanup(struct mt792x_dev *dev);
|
||||
int mt792x_dma_alloc_queues(struct mt792x_dev *dev,
|
||||
const struct mt792x_dma_layout *layout);
|
||||
int mt792x_dma_enable(struct mt792x_dev *dev);
|
||||
int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force);
|
||||
int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev);
|
||||
|
|
@ -459,6 +484,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
|
|||
return MT7922_FIRMWARE_WM;
|
||||
case 0x7925:
|
||||
return MT7925_FIRMWARE_WM;
|
||||
case 0x7927:
|
||||
return MT7927_FIRMWARE_WM;
|
||||
default:
|
||||
return MT7921_FIRMWARE_WM;
|
||||
}
|
||||
|
|
@ -475,6 +502,8 @@ static inline char *mt792x_patch_name(struct mt792x_dev *dev)
|
|||
return MT7922_ROM_PATCH;
|
||||
case 0x7925:
|
||||
return MT7925_ROM_PATCH;
|
||||
case 0x7927:
|
||||
return MT7927_ROM_PATCH;
|
||||
default:
|
||||
return MT7921_ROM_PATCH;
|
||||
}
|
||||
|
|
@ -489,6 +518,10 @@ int mt792xu_dma_init(struct mt792x_dev *dev, bool resume);
|
|||
int mt792xu_mcu_power_on(struct mt792x_dev *dev);
|
||||
int mt792xu_wfsys_reset(struct mt792x_dev *dev);
|
||||
int mt792xu_init_reset(struct mt792x_dev *dev);
|
||||
void mt792xu_reset_work_init(struct mt792x_dev *dev);
|
||||
void mt792xu_reset_work_cleanup(struct mt792x_dev *dev);
|
||||
int mt792xu_check_bus(struct mt792x_dev *dev);
|
||||
int mt792xu_reset_on_bus_error(struct mt792x_dev *dev);
|
||||
u32 mt792xu_rr(struct mt76_dev *dev, u32 addr);
|
||||
void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val);
|
||||
u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val);
|
||||
|
|
|
|||
|
|
@ -105,7 +105,8 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
|
|||
wcid = &mvif->sta.deflink.wcid;
|
||||
}
|
||||
|
||||
if (vif && control->sta && ieee80211_vif_is_mld(vif)) {
|
||||
if (vif && control->sta && ieee80211_vif_is_mld(vif) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct ieee80211_bss_conf *conf;
|
||||
|
|
@ -329,6 +330,47 @@ void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_flush);
|
||||
|
||||
int mt792x_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
unsigned int link_id, int *dbm)
|
||||
{
|
||||
struct mt76_power_limits limits = {};
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_vif *mvif;
|
||||
struct mt76_phy *phy;
|
||||
s8 max_power;
|
||||
|
||||
if (!vif)
|
||||
return mt76_get_txpower(hw, vif, link_id, dbm);
|
||||
|
||||
mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
phy = mvif->phy->mt76;
|
||||
|
||||
mt792x_mutex_acquire(mvif->phy->dev);
|
||||
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, link_id);
|
||||
mconf = link_conf ? mt792x_link_conf_to_mconf(link_conf) : NULL;
|
||||
if (mconf && mconf->mt76.ctx && mconf->mt76.ctx->def.chan)
|
||||
chan = mconf->mt76.ctx->def.chan;
|
||||
else
|
||||
/* Fall back to the current PHY chandef if the requested link
|
||||
* does not have a valid channel context.
|
||||
*/
|
||||
chan = phy->chandef.chan;
|
||||
|
||||
mt792x_mutex_release(mvif->phy->dev);
|
||||
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
max_power = mt76_connac_get_rate_power_limit(phy, chan, &limits);
|
||||
*dbm = DIV_ROUND_UP(max_power, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_get_txpower);
|
||||
|
||||
int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
|
|
@ -657,7 +699,6 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
|
|||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
wiphy->max_remain_on_channel_duration = 5000;
|
||||
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
|
||||
wiphy->max_scan_ssids = 4;
|
||||
wiphy->max_sched_scan_plan_interval =
|
||||
|
|
@ -759,6 +800,13 @@ mt792x_get_offload_capability(struct device *dev, const char *fw_wm)
|
|||
return offload_caps;
|
||||
}
|
||||
|
||||
static bool mt792x_needs_cnm_runtime(const void *drv_data)
|
||||
{
|
||||
const char *fw_wm = drv_data;
|
||||
|
||||
return fw_wm && !strcmp(fw_wm, MT7927_FIRMWARE_WM);
|
||||
}
|
||||
|
||||
struct ieee80211_ops *
|
||||
mt792x_get_mac80211_ops(struct device *dev,
|
||||
const struct ieee80211_ops *mac80211_ops,
|
||||
|
|
@ -772,6 +820,10 @@ mt792x_get_mac80211_ops(struct device *dev,
|
|||
return NULL;
|
||||
|
||||
*fw_features = mt792x_get_offload_capability(dev, drv_data);
|
||||
|
||||
if (mt792x_needs_cnm_runtime(drv_data))
|
||||
*fw_features |= MT792x_FW_CAP_CNM;
|
||||
|
||||
if (!(*fw_features & MT792x_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
|
|
|
|||
|
|
@ -87,22 +87,122 @@ void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete);
|
||||
|
||||
int mt792x_dma_alloc_queues(struct mt792x_dev *dev,
|
||||
const struct mt792x_dma_layout *layout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mt76_dma_attach(&dev->mt76);
|
||||
|
||||
ret = mt792x_dma_disable(dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* init tx queue */
|
||||
ret = mt76_connac_init_tx_queues(dev->phy.mt76, layout->tx_data0.qid,
|
||||
layout->tx_data0.n_desc,
|
||||
layout->tx_data0.ring_base,
|
||||
NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
|
||||
|
||||
/* command to WM */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM,
|
||||
layout->tx_mcu.qid,
|
||||
layout->tx_mcu.n_desc,
|
||||
layout->tx_mcu.ring_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* firmware download */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL,
|
||||
layout->tx_fwdl.qid,
|
||||
layout->tx_fwdl.n_desc,
|
||||
layout->tx_fwdl.ring_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rx event */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
|
||||
layout->rx_mcu.qid,
|
||||
layout->rx_mcu.n_desc,
|
||||
MT_RX_BUF_SIZE,
|
||||
layout->rx_mcu.ring_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rx data */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
|
||||
layout->rx_data.qid,
|
||||
layout->rx_data.n_desc,
|
||||
MT_RX_BUF_SIZE,
|
||||
layout->rx_data.ring_base);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_dma_alloc_queues);
|
||||
|
||||
#define PREFETCH(base, depth) ((base) << 16 | (depth))
|
||||
|
||||
static void mt7925_dma_prefetch_setup(struct mt792x_dev *dev)
|
||||
{
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4));
|
||||
|
||||
/* tx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0200, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0300, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));
|
||||
}
|
||||
|
||||
static void mt7925_wfdma_setup(struct mt792x_dev *dev)
|
||||
{
|
||||
mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
|
||||
mt76_set(dev, MT_WFDMA0_INT_RX_PRI, 0x0F00);
|
||||
mt76_set(dev, MT_WFDMA0_INT_TX_PRI, 0x7F00);
|
||||
}
|
||||
|
||||
static void mt7927_dma_prefetch_setup(struct mt792x_dev *dev)
|
||||
{
|
||||
mt76_wr(dev, MT_WFDMA_PREFETCH_CTRL,
|
||||
mt76_rr(dev, MT_WFDMA_PREFETCH_CTRL));
|
||||
mt76_wr(dev, MT_WFDMA_PREFETCH_CFG0, 0x660077);
|
||||
mt76_wr(dev, MT_WFDMA_PREFETCH_CFG1, 0x1100);
|
||||
mt76_wr(dev, MT_WFDMA_PREFETCH_CFG2, 0x30004f);
|
||||
mt76_wr(dev, MT_WFDMA_PREFETCH_CFG3, 0x542200);
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0x0000, 0x8));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING6_EXT_CTRL, PREFETCH(0x0080, 0x8));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING7_EXT_CTRL, PREFETCH(0x0100, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0140, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0180, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0280, 0x4));
|
||||
}
|
||||
|
||||
static void mt7927_wfdma_setup(struct mt792x_dev *dev)
|
||||
{
|
||||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_ADDR_EXT_EN |
|
||||
MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL);
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_CSR_LBK_RX_Q_SEL_EN);
|
||||
mt76_rmw(dev, MT_WFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
|
||||
mt76_set(dev, MT_WFDMA0_INT_RX_PRI, 0x0F00);
|
||||
mt76_set(dev, MT_WFDMA0_INT_TX_PRI, 0x7F00);
|
||||
}
|
||||
|
||||
static void mt792x_dma_prefetch(struct mt792x_dev *dev)
|
||||
{
|
||||
if (is_mt7925(&dev->mt76)) {
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4));
|
||||
/* tx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0200, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0300, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
mt7927_dma_prefetch_setup(dev);
|
||||
} else if (is_mt7925(&dev->mt76)) {
|
||||
mt7925_dma_prefetch_setup(dev);
|
||||
} else if (is_mt7902(&dev->mt76)) {
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
|
||||
|
|
@ -166,11 +266,11 @@ int mt792x_dma_enable(struct mt792x_dev *dev)
|
|||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
if (is_mt7925(&dev->mt76)) {
|
||||
mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
|
||||
mt76_set(dev, MT_WFDMA0_INT_RX_PRI, 0x0F00);
|
||||
mt76_set(dev, MT_WFDMA0_INT_TX_PRI, 0x7F00);
|
||||
}
|
||||
if (is_mt7927(&dev->mt76))
|
||||
mt7927_wfdma_setup(dev);
|
||||
else if (is_mt7925(&dev->mt76))
|
||||
mt7925_wfdma_setup(dev);
|
||||
|
||||
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
|
||||
/* enable interrupts for TX/RX rings */
|
||||
|
|
@ -281,6 +381,11 @@ int mt792x_dma_disable(struct mt792x_dev *dev, bool force)
|
|||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (is_mt7927(&dev->mt76)) {
|
||||
mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
|
||||
mt76_wr(dev, MT_WFDMA0_RST_DRX_PTR, ~0);
|
||||
}
|
||||
|
||||
/* disable dmashdl */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
|
||||
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
|
||||
|
|
@ -370,7 +475,54 @@ int mt792x_poll_rx(struct napi_struct *napi, int budget)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_poll_rx);
|
||||
|
||||
int mt792x_wfsys_reset(struct mt792x_dev *dev)
|
||||
static void mt7927_sema_status_read(struct mt792x_dev *dev, u32 addr)
|
||||
{
|
||||
u32 remap;
|
||||
|
||||
remap = mt76_rr(dev, MT7927_PCIE2AP_REMAP_WF_0_54);
|
||||
mt76_wr(dev, MT7927_PCIE2AP_REMAP_WF_0_54,
|
||||
(remap & ~MT7927_PCIE2AP_REMAP_WF_0_54_MASK) |
|
||||
MT7927_PCIE2AP_REMAP_WF_0_54_VAL);
|
||||
usleep_range(10, 20);
|
||||
|
||||
mt76_rr(dev, addr);
|
||||
|
||||
mt76_wr(dev, MT7927_PCIE2AP_REMAP_WF_0_54, remap);
|
||||
usleep_range(10, 20);
|
||||
}
|
||||
|
||||
static int mt7927_wfsys_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
u32 val;
|
||||
|
||||
mt7927_sema_status_read(dev, MT7927_SEMA_OWN_STA);
|
||||
|
||||
mt76_set(dev, MT7927_CBINFRA_RGU_WF_RST,
|
||||
MT7927_CBINFRA_RGU_WF_RST_WF_SUBSYS);
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
mt76_clear(dev, MT7927_CBINFRA_RGU_WF_RST,
|
||||
MT7927_CBINFRA_RGU_WF_RST_WF_SUBSYS);
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
mt76_wr(dev, MT7927_CBINFRA_MCU_OWN_SET, BIT(0));
|
||||
|
||||
if (!__mt76_poll_msec(mdev, MT7927_ROMCODE_INDEX, 0xffff,
|
||||
MT7927_MCU_IDLE_VALUE, 200)) {
|
||||
val = mt76_rr(dev, MT7927_ROMCODE_INDEX);
|
||||
dev_err(mdev->dev,
|
||||
"MT7927 WFSYS reset timeout (ROMCODE_INDEX=0x%04x)\n",
|
||||
val & 0xffff);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
mt7927_sema_status_read(dev, MT7927_SEMA_OWN_STA_REP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt792x_wfsys_reset_default(struct mt792x_dev *dev)
|
||||
{
|
||||
u32 addr = is_connac2(&dev->mt76) ? 0x18000140 : 0x7c000140;
|
||||
|
||||
|
|
@ -384,5 +536,13 @@ int mt792x_wfsys_reset(struct mt792x_dev *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt792x_wfsys_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
if (is_mt7927(&dev->mt76))
|
||||
return mt7927_wfsys_reset(dev);
|
||||
|
||||
return mt792x_wfsys_reset_default(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_wfsys_reset);
|
||||
|
||||
|
|
|
|||
|
|
@ -301,7 +301,9 @@
|
|||
#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
|
||||
#define MT_WFDMA0_GLO_CFG_RX_WB_DDONE BIT(13)
|
||||
#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
|
||||
#define MT_WFDMA0_GLO_CFG_CSR_LBK_RX_Q_SEL_EN BIT(20)
|
||||
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
|
||||
#define MT_WFDMA0_GLO_CFG_ADDR_EXT_EN BIT(26)
|
||||
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
|
||||
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
|
||||
#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30)
|
||||
|
|
@ -310,6 +312,9 @@
|
|||
#define HOST_RX_DONE_INT_ENA1 BIT(1)
|
||||
#define HOST_RX_DONE_INT_ENA2 BIT(2)
|
||||
#define HOST_RX_DONE_INT_ENA3 BIT(3)
|
||||
#define MT7927_RX_DONE_INT_ENA4 BIT(12)
|
||||
#define MT7927_RX_DONE_INT_ENA6 BIT(14)
|
||||
#define MT7927_RX_DONE_INT_ENA7 BIT(15)
|
||||
#define HOST_TX_DONE_INT_ENA0 BIT(4)
|
||||
#define HOST_TX_DONE_INT_ENA1 BIT(5)
|
||||
#define HOST_TX_DONE_INT_ENA2 BIT(6)
|
||||
|
|
@ -365,6 +370,13 @@
|
|||
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
|
||||
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
|
||||
|
||||
#define MT_WFDMA_PREFETCH_CTRL MT_WFDMA_EXT_CSR(0x30)
|
||||
#define MT_WFDMA_PREFETCH_CFG0 MT_WFDMA_EXT_CSR(0xf0)
|
||||
#define MT_WFDMA_PREFETCH_CFG1 MT_WFDMA_EXT_CSR(0xf4)
|
||||
#define MT_WFDMA_PREFETCH_CFG2 MT_WFDMA_EXT_CSR(0xf8)
|
||||
#define MT_WFDMA_PREFETCH_CFG3 MT_WFDMA_EXT_CSR(0xfc)
|
||||
#define MT_WFDMA0_GLO_CFG_EXT1 MT_WFDMA0(0x2b4)
|
||||
|
||||
#define MT_SWDEF_BASE 0x41f200
|
||||
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
|
||||
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
|
||||
|
|
@ -490,4 +502,15 @@
|
|||
#define WFSYS_SW_RST_B BIT(0)
|
||||
#define WFSYS_SW_INIT_DONE BIT(4)
|
||||
|
||||
/* CBInfra registers - MT7927 combo chip */
|
||||
#define MT7927_CBINFRA_RGU_WF_RST 0x1f8600
|
||||
#define MT7927_CBINFRA_RGU_WF_RST_WF_SUBSYS BIT(4)
|
||||
#define MT7927_CBINFRA_MCU_OWN_SET 0x1f5034
|
||||
#define MT7927_ROMCODE_INDEX 0xc1604
|
||||
#define MT7927_MCU_IDLE_VALUE 0x1d1e
|
||||
#define MT7927_PCIE2AP_REMAP_WF_0_54 0x21008
|
||||
#define MT7927_PCIE2AP_REMAP_WF_0_54_MASK GENMASK(15, 0)
|
||||
#define MT7927_PCIE2AP_REMAP_WF_0_54_VAL 0x00001807
|
||||
#define MT7927_SEMA_OWN_STA 0x40000
|
||||
#define MT7927_SEMA_OWN_STA_REP 0x40400
|
||||
#endif /* __MT792X_REGS_H */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,81 @@
|
|||
#include "mt792x.h"
|
||||
#include "mt76_connac2_mac.h"
|
||||
|
||||
static int mt792xu_read32(struct mt76_dev *dev, u32 addr, void *buf)
|
||||
{
|
||||
return __mt76u_vendor_request(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | MT_USB_TYPE_VENDOR,
|
||||
(u16)(addr >> 16), (u16)addr,
|
||||
buf, sizeof(__le32));
|
||||
}
|
||||
|
||||
static void mt792xu_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct mt792x_dev *dev =
|
||||
container_of(work, struct mt792x_dev, usb_reset_work);
|
||||
struct usb_interface *usb_intf = to_usb_interface(dev->mt76.dev);
|
||||
|
||||
if (usb_intf && usb_get_intfdata(usb_intf) == dev)
|
||||
usb_queue_reset_device(usb_intf);
|
||||
|
||||
atomic_set(&dev->usb_reset_pending, 0);
|
||||
}
|
||||
|
||||
void mt792xu_reset_work_init(struct mt792x_dev *dev)
|
||||
{
|
||||
INIT_WORK(&dev->usb_reset_work, mt792xu_reset_work);
|
||||
atomic_set(&dev->usb_reset_pending, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792xu_reset_work_init);
|
||||
|
||||
void mt792xu_reset_work_cleanup(struct mt792x_dev *dev)
|
||||
{
|
||||
cancel_work_sync(&dev->usb_reset_work);
|
||||
atomic_set(&dev->usb_reset_pending, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792xu_reset_work_cleanup);
|
||||
|
||||
int mt792xu_check_bus(struct mt792x_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->mt76.usb.usb_ctrl_mtx);
|
||||
ret = mt792xu_read32(&dev->mt76, MT_HW_CHIPID, dev->mt76.usb.data);
|
||||
mutex_unlock(&dev->mt76.usb.usb_ctrl_mtx);
|
||||
|
||||
if (ret == sizeof(__le32))
|
||||
return 0;
|
||||
|
||||
return ret < 0 ? ret : -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792xu_check_bus);
|
||||
|
||||
int mt792xu_reset_on_bus_error(struct mt792x_dev *dev)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!atomic_read(&dev->mt76.bus_hung))
|
||||
err = mt792xu_check_bus(dev);
|
||||
|
||||
if (err) {
|
||||
atomic_set(&dev->mt76.bus_hung, true);
|
||||
|
||||
if (!atomic_xchg(&dev->usb_reset_pending, 1)) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"USB transport access failed (%d), queueing device reset\n",
|
||||
err);
|
||||
|
||||
schedule_work(&dev->usb_reset_work);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_set(&dev->mt76.bus_hung, false);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792xu_reset_on_bus_error);
|
||||
|
||||
u32 mt792xu_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
|
@ -263,7 +338,7 @@ EXPORT_SYMBOL_GPL(mt792xu_dma_init);
|
|||
|
||||
int mt792xu_wfsys_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
const struct mt792xu_wfsys_desc *desc = is_mt7925(&dev->mt76) ?
|
||||
const struct mt792xu_wfsys_desc *desc = is_connac3(&dev->mt76) ?
|
||||
&mt7925_wfsys_desc :
|
||||
&mt7921_wfsys_desc;
|
||||
u32 val;
|
||||
|
|
@ -333,6 +408,7 @@ void mt792xu_disconnect(struct usb_interface *usb_intf)
|
|||
{
|
||||
struct mt792x_dev *dev = usb_get_intfdata(usb_intf);
|
||||
|
||||
mt792xu_reset_work_cleanup(dev);
|
||||
cancel_work_sync(&dev->init_work);
|
||||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return;
|
||||
|
|
@ -341,7 +417,6 @@ void mt792xu_disconnect(struct usb_interface *usb_intf)
|
|||
mt792xu_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -664,7 +664,7 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
|
|||
if (!mlink)
|
||||
continue;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -875,8 +875,6 @@ int mt7996_init_debugfs(struct mt7996_dev *dev)
|
|||
struct dentry *dir;
|
||||
|
||||
dir = mt76_register_debugfs_fops(&dev->mphy, NULL);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
debugfs_create_file("hw-queues", 0400, dir, dev,
|
||||
&mt7996_hw_queues_fops);
|
||||
|
|
@ -1042,7 +1040,7 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file,
|
|||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_sta->link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_sta->link_id);
|
||||
if (!msta_link) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
|||
ret = mt7996_init_tx_queues(&dev->phy, MT_TXQ_ID(0),
|
||||
MT7996_NPU_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(0) + hif1_ofs,
|
||||
NULL);
|
||||
wed);
|
||||
else
|
||||
ret = mt7996_init_tx_queues(&dev->phy,
|
||||
MT_TXQ_ID(dev->mphy.band_idx),
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
|||
if (mlink->band_idx != band_idx)
|
||||
continue;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[i]);
|
||||
msta_link = mt7996_sta_link(msta, i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -757,6 +757,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
|||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
u16 seqno = le16_to_cpu(sc);
|
||||
bool hw_bigtk = false;
|
||||
u8 fc_type, fc_stype;
|
||||
|
|
@ -819,7 +820,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
|||
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
|
||||
}
|
||||
|
||||
if (multicast && ieee80211_vif_is_mld(info->control.vif)) {
|
||||
if (multicast && vif && ieee80211_vif_is_mld(vif)) {
|
||||
val = MT_TXD3_SN_VALID |
|
||||
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
|
||||
txwi[3] |= cpu_to_le32(val);
|
||||
|
|
@ -839,12 +840,12 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
|||
txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mld(info->control.vif) &&
|
||||
if (vif && ieee80211_vif_is_mld(vif) &&
|
||||
(multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))))
|
||||
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
|
||||
|
||||
if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) &&
|
||||
ieee80211_vif_is_mld(info->control.vif)) {
|
||||
vif && ieee80211_vif_is_mld(vif)) {
|
||||
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
|
||||
txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
|
||||
}
|
||||
|
|
@ -856,7 +857,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
|||
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed)
|
||||
enum mt76_txq_id qid, u32 changed,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
|
@ -866,7 +868,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
struct mt76_vif_link *mlink = NULL;
|
||||
struct mt7996_vif *mvif;
|
||||
unsigned int link_id;
|
||||
u16 tx_count = 15;
|
||||
u32 val;
|
||||
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
|
|
@ -874,17 +875,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
|
||||
|
||||
if (wcid != &dev->mt76.global_wcid)
|
||||
link_id = wcid->link_id;
|
||||
else
|
||||
link_id = u32_get_bits(info->control.flags,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
|
||||
if (mvif) {
|
||||
if (wcid->offchannel)
|
||||
mlink = rcu_dereference(mvif->mt76.offchannel_link);
|
||||
if (!mlink)
|
||||
if (!mlink && link_id != IEEE80211_LINK_UNSPECIFIED)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
}
|
||||
|
||||
|
|
@ -1038,7 +1033,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
if (link_id != wcid->link_id && link_id != IEEE80211_LINK_UNSPECIFIED) {
|
||||
if (msta) {
|
||||
struct mt7996_sta_link *msta_link =
|
||||
rcu_dereference(msta->link[link_id]);
|
||||
mt7996_sta_link(msta, link_id);
|
||||
|
||||
if (msta_link)
|
||||
wcid = &msta_link->wcid;
|
||||
|
|
@ -1067,11 +1062,11 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
|
||||
link_conf = rcu_dereference(vif->link_conf[wcid->link_id]);
|
||||
if (!link_conf)
|
||||
return -EINVAL;
|
||||
goto error_release_token;
|
||||
|
||||
link_sta = rcu_dereference(sta->link[wcid->link_id]);
|
||||
if (!link_sta)
|
||||
return -EINVAL;
|
||||
goto error_release_token;
|
||||
|
||||
dma_sync_single_for_cpu(mdev->dma_dev, tx_info->buf[1].addr,
|
||||
tx_info->buf[1].len, DMA_TO_DEVICE);
|
||||
|
|
@ -1096,7 +1091,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
/* Transmit non qos data by 802.11 header and need to fill txd by host*/
|
||||
if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
|
||||
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, qid, 0);
|
||||
pid, qid, 0, link_id);
|
||||
|
||||
/* MT7996 and MT7992 require driver to provide the MAC TXP for AddBA
|
||||
* req
|
||||
|
|
@ -1176,6 +1171,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
|
||||
|
||||
return 0;
|
||||
|
||||
error_release_token:
|
||||
mt76_token_release(mdev, id, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
|
||||
|
|
@ -1346,7 +1345,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
|||
IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[id]);
|
||||
msta_link = mt7996_sta_link(msta, id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -1360,13 +1359,13 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
|||
cur_info++;
|
||||
continue;
|
||||
} else if (info & MT_TXFREE_INFO_HEADER) {
|
||||
u32 tx_retries = 0, tx_failed = 0;
|
||||
u32 tx_retries = 0, tx_failed = 0, count;
|
||||
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
tx_retries =
|
||||
FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
|
||||
count = FIELD_GET(MT_TXFREE_INFO_COUNT, info);
|
||||
tx_retries = count ? count - 1 : 0;
|
||||
tx_failed = tx_retries +
|
||||
!!FIELD_GET(MT_TXFREE_INFO_STAT, info);
|
||||
|
||||
|
|
@ -2059,8 +2058,6 @@ void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
|
|||
{
|
||||
s16 coverage_class = phy->coverage_class;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
struct mt7996_phy *phy2 = mt7996_phy2(dev);
|
||||
struct mt7996_phy *phy3 = mt7996_phy3(dev);
|
||||
u32 reg_offset;
|
||||
u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
|
||||
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
|
||||
|
|
@ -2072,14 +2069,6 @@ void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
|
|||
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
|
||||
return;
|
||||
|
||||
if (phy2)
|
||||
coverage_class = max_t(s16, dev->phy.coverage_class,
|
||||
phy2->coverage_class);
|
||||
|
||||
if (phy3)
|
||||
coverage_class = max_t(s16, coverage_class,
|
||||
phy3->coverage_class);
|
||||
|
||||
offset = 3 * coverage_class;
|
||||
reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
|
||||
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
|
||||
|
|
|
|||
|
|
@ -207,8 +207,7 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
struct mt7996_sta *msta;
|
||||
|
||||
msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
msta_link = mt76_dereference(msta->link[link_id],
|
||||
&dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1164,6 +1163,9 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
|
|||
msta_link->wcid.link_valid = !!sta->valid_links;
|
||||
msta_link->wcid.def_wcid = &msta->deflink.wcid;
|
||||
|
||||
if (link_sta->sta->tdls)
|
||||
set_bit(MT_WCID_FLAG_TDLS_PEER, &msta_link->wcid.flags);
|
||||
|
||||
ewma_avg_signal_init(&msta_link->avg_ack_signal);
|
||||
ewma_signal_init(&msta_link->wcid.rssi);
|
||||
|
||||
|
|
@ -1381,7 +1383,7 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||
if (!link)
|
||||
continue;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -1573,7 +1575,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
|
|||
if (msta) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_id);
|
||||
if (msta_link)
|
||||
wcid = &msta_link->wcid;
|
||||
}
|
||||
|
|
@ -1944,7 +1946,7 @@ static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw,
|
|||
|
||||
rcu_read_lock();
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_sta->link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_sta->link_id);
|
||||
if (msta_link) {
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
|
||||
|
|
@ -1959,9 +1961,13 @@ static void mt7996_sta_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
|
|||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
u32 *changed = data;
|
||||
struct mt7996_vif *mvif = data;
|
||||
u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[msta->deflink_id]);
|
||||
if (msta->vif != mvif)
|
||||
return;
|
||||
|
||||
msta_link = mt7996_sta_link(msta, msta->deflink_id);
|
||||
if (msta_link)
|
||||
mt7996_link_rate_ctrl_update(&changed, msta_link);
|
||||
}
|
||||
|
|
@ -1972,7 +1978,6 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
|
||||
|
||||
mvif->deflink.bitrate_mask = *mask;
|
||||
|
||||
|
|
@ -1985,7 +1990,7 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
* then multiple MCS setting (MCS 4,5,6) is not supported.
|
||||
*/
|
||||
ieee80211_iterate_stations_atomic(hw, mt7996_sta_rate_ctrl_update,
|
||||
&changed);
|
||||
mvif);
|
||||
ieee80211_queue_work(hw, &dev->rc_work);
|
||||
|
||||
return 0;
|
||||
|
|
@ -2011,7 +2016,7 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
|
|||
if (!link)
|
||||
continue;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -2049,7 +2054,7 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
|
|||
if (!link)
|
||||
continue;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -2389,7 +2394,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
|
|||
if (!link)
|
||||
return -EIO;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[msta->deflink_id]);
|
||||
msta_link = mt7996_sta_link(msta, msta->deflink_id);
|
||||
if (!msta_link)
|
||||
return -EIO;
|
||||
|
||||
|
|
|
|||
|
|
@ -1136,7 +1136,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
|
|||
struct mt7996_sta_link *msta_link;
|
||||
int link_id = link_conf->link_id;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_id);
|
||||
if (msta_link)
|
||||
sta_wlan_idx = msta_link->wcid.idx;
|
||||
}
|
||||
|
|
@ -1281,6 +1281,10 @@ int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *li
|
|||
PROT_NONGF_STA = BIT(7),
|
||||
};
|
||||
|
||||
/* The current firmware causes TX failure. Need further investigation */
|
||||
if (is_mt7996(&dev->mt76))
|
||||
return 0;
|
||||
|
||||
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
|
||||
MT7996_BSS_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
|
|
@ -1429,7 +1433,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
|
|||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -1463,7 +1467,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
|
|||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -2139,6 +2143,11 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
|||
hdr_trans->from_ds = true;
|
||||
hdr_trans->mesh = true;
|
||||
}
|
||||
|
||||
if (test_bit(MT_WCID_FLAG_TDLS_PEER, &wcid->flags)) {
|
||||
hdr_trans->to_ds = false;
|
||||
hdr_trans->from_ds = false;
|
||||
}
|
||||
}
|
||||
|
||||
static enum mcu_mmps_mode
|
||||
|
|
@ -2200,7 +2209,7 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
|||
if (!mlink)
|
||||
goto error_unlock;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_id);
|
||||
if (!msta_link)
|
||||
goto error_unlock;
|
||||
|
||||
|
|
@ -2290,7 +2299,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
|||
if (!link)
|
||||
goto error_unlock;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_id);
|
||||
if (!msta_link)
|
||||
goto error_unlock;
|
||||
|
||||
|
|
@ -2508,7 +2517,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
|||
if (!link)
|
||||
goto error_unlock;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
msta_link = mt7996_sta_link(msta, link_id);
|
||||
if (!msta_link)
|
||||
goto error_unlock;
|
||||
|
||||
|
|
@ -2663,7 +2672,7 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
|||
unsigned int link_id;
|
||||
struct tlv *tlv;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[msta->deflink_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, msta->deflink_id);
|
||||
if (!msta_link)
|
||||
return;
|
||||
|
||||
|
|
@ -2677,8 +2686,8 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
|||
mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
|
||||
|
||||
if (nlinks > 1) {
|
||||
msta_link = mt76_dereference(msta->link[msta->seclink_id],
|
||||
&dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta,
|
||||
msta->seclink_id);
|
||||
if (!msta_link)
|
||||
return;
|
||||
}
|
||||
|
|
@ -2689,7 +2698,7 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
|||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
|
|
@ -2837,7 +2846,7 @@ void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta)
|
|||
if (!link_sta)
|
||||
return;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
|
||||
if (!msta_link)
|
||||
return;
|
||||
|
||||
|
|
@ -3098,7 +3107,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev,
|
|||
|
||||
buf = (u8 *)bcn + sizeof(*bcn);
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
|
||||
BSS_CHANGED_BEACON);
|
||||
BSS_CHANGED_BEACON, link_conf->link_id);
|
||||
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
}
|
||||
|
|
@ -3244,7 +3253,8 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
|||
|
||||
buf = (u8 *)tlv + sizeof(*discov);
|
||||
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
|
||||
changed, link_conf->link_id);
|
||||
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
|
||||
|
|
|
|||
|
|
@ -642,6 +642,25 @@ mt7996_vif_conf_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||
link_conf);
|
||||
}
|
||||
|
||||
static inline struct mt7996_sta_link *
|
||||
mt7996_sta_link(struct mt7996_sta *msta, u8 link_id)
|
||||
{
|
||||
if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
|
||||
return NULL;
|
||||
|
||||
return rcu_dereference(msta->link[link_id]);
|
||||
}
|
||||
|
||||
static inline struct mt7996_sta_link *
|
||||
mt7996_sta_link_protected(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
u8 link_id)
|
||||
{
|
||||
if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
|
||||
return NULL;
|
||||
|
||||
return mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
}
|
||||
|
||||
#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)
|
||||
|
|
@ -855,7 +874,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
|
|||
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
enum mt76_txq_id qid, u32 changed,
|
||||
unsigned int link_id);
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy);
|
||||
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
|
||||
void mt7996_mac_work(struct work_struct *work);
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
|
|||
dev->hif2 = hif2;
|
||||
|
||||
mt76_npu_init(mdev, pci_resource_start(pdev, 0),
|
||||
pdev->bus && pci_domain_nr(pdev->bus) ? 3 : 2);
|
||||
pci_domain_nr(pdev->bus) ? 3 : 2);
|
||||
|
||||
ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
|
||||
if (ret < 0)
|
||||
|
|
|
|||
|
|
@ -30,8 +30,14 @@ void mt76_pci_disable_aspm(struct pci_dev *pdev)
|
|||
|
||||
if (IS_ENABLED(CONFIG_PCIEASPM)) {
|
||||
int err;
|
||||
int state = 0;
|
||||
|
||||
err = pci_disable_link_state(pdev, aspm_conf);
|
||||
if (aspm_conf & PCI_EXP_LNKCTL_ASPM_L0S)
|
||||
state |= PCIE_LINK_STATE_L0S;
|
||||
if (aspm_conf & PCI_EXP_LNKCTL_ASPM_L1)
|
||||
state |= PCIE_LINK_STATE_L1;
|
||||
|
||||
err = pci_disable_link_state(pdev, state);
|
||||
if (!err)
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -933,7 +933,7 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
|
||||
if (wake && dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
|
||||
dev->phy.q_tx[0]->blocked)
|
||||
*wake = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -925,6 +925,8 @@ mt76u_ac_to_hwq(struct mt76_dev *dev, struct mt76_queue *q, u8 qid)
|
|||
q->ep = q->hw_idx + 1;
|
||||
break;
|
||||
}
|
||||
case 0x6639:
|
||||
case 0x7902:
|
||||
case 0x7961:
|
||||
case 0x7925:
|
||||
q->hw_idx = mt76_ac_to_hwq(ac);
|
||||
|
|
|
|||
|
|
@ -274,7 +274,6 @@ static int mt7601u_probe(struct usb_interface *usb_intf,
|
|||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
usb_dev = usb_get_dev(usb_dev);
|
||||
usb_reset_device(usb_dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
|
@ -319,7 +318,6 @@ static int mt7601u_probe(struct usb_interface *usb_intf,
|
|||
mt7601u_cleanup(dev);
|
||||
err:
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
destroy_workqueue(dev->stat_wq);
|
||||
ieee80211_free_hw(dev->hw);
|
||||
|
|
@ -334,7 +332,6 @@ static void mt7601u_disconnect(struct usb_interface *usb_intf)
|
|||
mt7601u_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
destroy_workqueue(dev->stat_wq);
|
||||
ieee80211_free_hw(dev->hw);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user