wireless-next patches for v5.18
Third set of patches for v5.18. Smaller set this time, support for mt7921u and some work on MBSSID support. Also a workaround for rfkill userspace event. Major changes: mac80211 * MBSSID beacon handling in AP mode rfkill * make new event layout opt-in to workaround buggy user space rtlwifi * support On Networks N150 device id mt76 * mt7915: MBSSID and 6 GHz band support * new driver mt7921u -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmI0mvgRHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZs34wf/W+/0S69czX+mBJ85DQfXDuQ2TGVFJxeQ Ua5Xhd2J+pe6wVqIdGGl8yepi+CYsDkdHNB9dc8j52I3iPd3VAsOIkQv3jKJEM9Z YUm90PW3KOyFy2XUGve+S+YciQ2iHBm/BJnpioVfHrA8ltRbPLo4wZutuvc1IF+s sqFsKjM6Kewc6DE0UISuXqf9Xp0CIKo5uq1pC+M1UiETai+zLqKrBeAU3f7Zqq3J IeGjOYTFn9BMjt9yyLcTuMxUKr9rcI4XvAjRgdUdf5Us1i2R9skiKK93L67qDEUQ kudvfSuxfSaJd0hU65/QGXUlxmu9DrSxZwVpyUgG7E5CW2GGnLbGaw== =8q/O -----END PGP SIGNATURE----- Merge tag 'wireless-next-2022-03-18' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Kalle Valo says: ==================== wireless-next patches for v5.18 Third set of patches for v5.18. Smaller set this time, support for mt7921u and some work on MBSSID support. Also a workaround for rfkill userspace event. Major changes: mac80211 * MBSSID beacon handling in AP mode rfkill * make new event layout opt-in to workaround buggy user space rtlwifi * support On Networks N150 device id mt76 * mt7915: MBSSID and 6 GHz band support * new driver mt7921u ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
dca51fe7fb
|
@ -15938,8 +15938,8 @@ M: Kalle Valo <kvalo@kernel.org>
|
|||
L: ath11k@lists.infradead.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
F: Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
|
||||
F: drivers/net/wireless/ath/ath11k/
|
||||
F: Documentation/devicetree/bindings/net/wireless/qcom,ath11k.txt
|
||||
|
||||
QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
|
||||
M: Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
#define P2PSD_ACTION_CATEGORY 0x04 /* Public action frame */
|
||||
#define P2PSD_ACTION_ID_GAS_IREQ 0x0a /* GAS Initial Request AF */
|
||||
#define P2PSD_ACTION_ID_GAS_IRESP 0x0b /* GAS Initial Response AF */
|
||||
#define P2PSD_ACTION_ID_GAS_CREQ 0x0c /* GAS Comback Request AF */
|
||||
#define P2PSD_ACTION_ID_GAS_CRESP 0x0d /* GAS Comback Response AF */
|
||||
#define P2PSD_ACTION_ID_GAS_CREQ 0x0c /* GAS Comeback Request AF */
|
||||
#define P2PSD_ACTION_ID_GAS_CRESP 0x0d /* GAS Comeback Response AF */
|
||||
|
||||
#define BRCMF_P2P_DISABLE_TIMEOUT msecs_to_jiffies(500)
|
||||
|
||||
|
@ -396,11 +396,11 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
|
|||
(tx) ? "TX" : "RX");
|
||||
break;
|
||||
case P2PSD_ACTION_ID_GAS_CREQ:
|
||||
brcmf_dbg(TRACE, "%s P2P GAS Comback Request\n",
|
||||
brcmf_dbg(TRACE, "%s P2P GAS Comeback Request\n",
|
||||
(tx) ? "TX" : "RX");
|
||||
break;
|
||||
case P2PSD_ACTION_ID_GAS_CRESP:
|
||||
brcmf_dbg(TRACE, "%s P2P GAS Comback Response\n",
|
||||
brcmf_dbg(TRACE, "%s P2P GAS Comeback Response\n",
|
||||
(tx) ? "TX" : "RX");
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -545,7 +545,7 @@ struct ConfigRid {
|
|||
#define MODE_CFG_MASK cpu_to_le16(0xff)
|
||||
#define MODE_ETHERNET_HOST cpu_to_le16(0<<8) /* rx payloads converted */
|
||||
#define MODE_LLC_HOST cpu_to_le16(1<<8) /* rx payloads left as is */
|
||||
#define MODE_AIRONET_EXTEND cpu_to_le16(1<<9) /* enable Aironet extenstions */
|
||||
#define MODE_AIRONET_EXTEND cpu_to_le16(1<<9) /* enable Aironet extensions */
|
||||
#define MODE_AP_INTERFACE cpu_to_le16(1<<10) /* enable ap interface extensions */
|
||||
#define MODE_ANTENNA_ALIGN cpu_to_le16(1<<11) /* enable antenna alignment */
|
||||
#define MODE_ETHER_LLC cpu_to_le16(1<<12) /* enable ethernet LLC */
|
||||
|
|
|
@ -139,6 +139,7 @@ config IWLMEI
|
|||
tristate "Intel Management Engine communication over WLAN"
|
||||
depends on INTEL_MEI
|
||||
depends on PM
|
||||
depends on CFG80211
|
||||
help
|
||||
Enables the iwlmei kernel module.
|
||||
|
||||
|
|
|
@ -389,7 +389,7 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
|||
{
|
||||
const u8 *vendor_ie;
|
||||
const u8 *wmm_ie;
|
||||
u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
|
||||
static const u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
|
||||
|
||||
vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
|
||||
WLAN_OUI_TYPE_MICROSOFT_WMM,
|
||||
|
|
|
@ -942,10 +942,11 @@ mt76_rx_signal(struct mt76_rx_status *status)
|
|||
for (chains = status->chains; chains; chains >>= 1, chain_signal++) {
|
||||
int cur, diff;
|
||||
|
||||
if (!(chains & BIT(0)))
|
||||
cur = *chain_signal;
|
||||
if (!(chains & BIT(0)) ||
|
||||
cur > 0)
|
||||
continue;
|
||||
|
||||
cur = *chain_signal;
|
||||
if (cur > signal)
|
||||
swap(cur, signal);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#define MT_MCU_RING_SIZE 32
|
||||
#define MT_RX_BUF_SIZE 2048
|
||||
#define MT_SKB_HEAD_LEN 128
|
||||
#define MT_SKB_HEAD_LEN 256
|
||||
|
||||
#define MT_MAX_NON_AQL_PKT 16
|
||||
#define MT_TXQ_FREE_THR 32
|
||||
|
@ -1274,13 +1274,21 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
|
|||
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
|
||||
struct mt76_sta_stats *stats);
|
||||
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
|
||||
int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u16 val, u16 offset, void *buf, size_t len);
|
||||
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
u8 req_type, u16 val, u16 offset,
|
||||
void *buf, size_t len);
|
||||
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
|
||||
const u16 offset, const u32 val);
|
||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
||||
bool ext);
|
||||
void mt76u_read_copy(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len);
|
||||
u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr);
|
||||
void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u32 addr, u32 val);
|
||||
int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
||||
struct mt76_bus_ops *ops);
|
||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
|
||||
int mt76u_alloc_mcu_queue(struct mt76_dev *dev);
|
||||
int mt76u_alloc_queues(struct mt76_dev *dev);
|
||||
void mt76u_stop_tx(struct mt76_dev *dev);
|
||||
|
|
|
@ -76,7 +76,7 @@ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
|||
__le32 *end = (__le32 *)&skb->data[skb->len];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
if (q == MT_RXQ_MCU) {
|
||||
if (type == PKT_TYPE_RX_EVENT)
|
||||
|
|
|
@ -1130,7 +1130,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta,
|
|||
}
|
||||
|
||||
rate_set_tsf = READ_ONCE(sta->rate_set_tsf);
|
||||
rs_idx = !((u32)(FIELD_GET(MT_TXS1_F0_TIMESTAMP, le32_to_cpu(txs_data[1])) -
|
||||
rs_idx = !((u32)(le32_get_bits(txs_data[1], MT_TXS1_F0_TIMESTAMP) -
|
||||
rate_set_tsf) < 1000000);
|
||||
rs_idx ^= rate_set_tsf & BIT(0);
|
||||
rs = &sta->rateset[rs_idx];
|
||||
|
@ -1244,14 +1244,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
|
|||
struct mt7603_sta *msta = NULL;
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u32 txs;
|
||||
u8 wcidx;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[4]);
|
||||
pid = FIELD_GET(MT_TXS4_PID, txs);
|
||||
txs = le32_to_cpu(txs_data[3]);
|
||||
wcidx = FIELD_GET(MT_TXS3_WCID, txs);
|
||||
pid = le32_get_bits(txs_data[4], MT_TXS4_PID);
|
||||
wcidx = le32_get_bits(txs_data[3], MT_TXS3_WCID);
|
||||
|
||||
if (pid == MT_PACKET_ID_NO_ACK)
|
||||
return;
|
||||
|
|
|
@ -261,7 +261,7 @@ static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
|||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (FIELD_GET(MT_RXD1_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[1])) !=
|
||||
if (le32_get_bits(rxd[1], MT_RXD1_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD1_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1427,7 +1427,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
|
|||
}
|
||||
|
||||
rate_set_tsf = READ_ONCE(sta->rate_set_tsf);
|
||||
rs_idx = !((u32)(FIELD_GET(MT_TXS4_F0_TIMESTAMP, le32_to_cpu(txs_data[4])) -
|
||||
rs_idx = !((u32)(le32_get_bits(txs_data[4], MT_TXS4_F0_TIMESTAMP) -
|
||||
rate_set_tsf) < 1000000);
|
||||
rs_idx ^= rate_set_tsf & BIT(0);
|
||||
rs = &sta->rateset[rs_idx];
|
||||
|
@ -1558,14 +1558,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
|
|||
struct mt76_wcid *wcid;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
__le32 *txs_data = data;
|
||||
u32 txs;
|
||||
u8 wcidx;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
pid = FIELD_GET(MT_TXS0_PID, txs);
|
||||
txs = le32_to_cpu(txs_data[2]);
|
||||
wcidx = FIELD_GET(MT_TXS2_WCID, txs);
|
||||
pid = le32_get_bits(txs_data[0], MT_TXS0_PID);
|
||||
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
|
||||
|
||||
if (pid == MT_PACKET_ID_NO_ACK)
|
||||
return;
|
||||
|
@ -1653,7 +1650,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
|
|||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);
|
||||
}
|
||||
|
||||
count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl));
|
||||
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT);
|
||||
if (is_mt7615(&dev->mt76)) {
|
||||
__le16 *token = &free->token[0];
|
||||
|
||||
|
@ -1686,7 +1683,8 @@ bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len)
|
|||
__le32 *end = (__le32 *)&rxd[len / 4];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7615_mac_tx_free(dev, data, len);
|
||||
|
@ -1710,8 +1708,8 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
|||
enum rx_pkt_type type;
|
||||
u16 flag;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);
|
||||
if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
|
||||
type = PKT_TYPE_NORMAL_MCU;
|
||||
|
||||
|
|
|
@ -880,7 +880,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
|||
NULL, wtbl_hdr);
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
|
||||
NULL, wtbl_hdr, true);
|
||||
NULL, wtbl_hdr, true, true);
|
||||
mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,
|
||||
NULL, wtbl_hdr);
|
||||
}
|
||||
|
@ -2151,7 +2151,8 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
|
|||
.center_chan2 = ieee80211_frequency_to_channel(freq2),
|
||||
};
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
|
|
|
@ -559,6 +559,7 @@ void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
|||
struct mt76_queue_entry *e);
|
||||
int mt7663_usb_sdio_register_device(struct mt7615_dev *dev);
|
||||
int mt7663u_mcu_init(struct mt7615_dev *dev);
|
||||
int mt7663u_mcu_power_on(struct mt7615_dev *dev);
|
||||
|
||||
/* sdio */
|
||||
int mt7663s_mcu_init(struct mt7615_dev *dev);
|
||||
|
|
|
@ -21,6 +21,64 @@ static const struct usb_device_id mt7615_device_table[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static u32 mt7663u_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7663u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static u32 mt7663u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask;
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt7663u_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int ret, i = 0, batch_len;
|
||||
const u8 *val = data;
|
||||
|
||||
len = round_up(len, 4);
|
||||
|
||||
mutex_lock(&usb->usb_ctrl_mtx);
|
||||
while (i < len) {
|
||||
batch_len = min_t(int, usb->data_len, len - i);
|
||||
memcpy(usb->data, val + i, batch_len);
|
||||
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
(offset + i) >> 16, offset + i,
|
||||
usb->data, batch_len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
i += batch_len;
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt7663u_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
|
@ -66,6 +124,14 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
|||
.sta_remove = mt7615_mac_sta_remove,
|
||||
.update_survey = mt7615_update_channel,
|
||||
};
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt7663u_rr,
|
||||
.wr = mt7663u_wr,
|
||||
.rmw = mt7663u_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt7663u_copy,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(usb_intf);
|
||||
struct ieee80211_ops *ops;
|
||||
struct mt7615_dev *dev;
|
||||
|
@ -92,7 +158,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
|||
INIT_WORK(&dev->mcu_work, mt7663u_init_work);
|
||||
dev->reg_map = mt7663_usb_sdio_reg_map;
|
||||
dev->ops = ops;
|
||||
ret = mt76u_init(mdev, usb_intf, true);
|
||||
ret = __mt76u_init(mdev, usb_intf, &bus_ops);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -100,27 +166,15 @@ static int mt7663u_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_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_dbg(dev->mt76.dev, "Usb device already powered on\n");
|
||||
set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state);
|
||||
goto alloc_queues;
|
||||
}
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
ret = mt7663u_mcu_power_on(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
} else {
|
||||
set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state);
|
||||
}
|
||||
|
||||
alloc_queues:
|
||||
ret = mt76u_alloc_mcu_queue(&dev->mt76);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
|
|
@ -42,6 +42,26 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int mt7663u_mcu_power_on(struct mt7615_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7663u_mcu_init(struct mt7615_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7663u_mcu_ops = {
|
||||
|
@ -57,23 +77,17 @@ int mt7663u_mcu_init(struct mt7615_dev *dev)
|
|||
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) {
|
||||
mt7615_mcu_restart(&dev->mt76);
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON, 0, 500))
|
||||
return -EIO;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
ret = mt7615_mcu_restart(&dev->mt76);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
MT_TOP_MISC2_FW_PWR_ON, 0, 500))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = mt7663u_mcu_power_on(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __mt7663_load_firmware(dev);
|
||||
|
|
|
@ -899,24 +899,33 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_smps_tlv);
|
|||
|
||||
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, void *sta_wtbl,
|
||||
void *wtbl_tlv, bool ldpc)
|
||||
void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc)
|
||||
{
|
||||
struct wtbl_ht *ht = NULL;
|
||||
struct tlv *tlv;
|
||||
u32 flags = 0;
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
if (sta->ht_cap.ht_supported || sta->he_6ghz_capa.capa) {
|
||||
tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht),
|
||||
wtbl_tlv, sta_wtbl);
|
||||
ht = (struct wtbl_ht *)tlv;
|
||||
ht->ldpc = ldpc &&
|
||||
ht->ldpc = ht_ldpc &&
|
||||
!!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING);
|
||||
ht->af = sta->ht_cap.ampdu_factor;
|
||||
ht->mm = sta->ht_cap.ampdu_density;
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
ht->af = sta->ht_cap.ampdu_factor;
|
||||
ht->mm = sta->ht_cap.ampdu_density;
|
||||
} else {
|
||||
ht->af = le16_get_bits(sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
|
||||
ht->mm = le16_get_bits(sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
|
||||
}
|
||||
|
||||
ht->ht = true;
|
||||
}
|
||||
|
||||
if (sta->vht_cap.vht_supported) {
|
||||
if (sta->vht_cap.vht_supported || sta->he_6ghz_capa.capa) {
|
||||
struct wtbl_vht *vht;
|
||||
u8 af;
|
||||
|
||||
|
@ -924,7 +933,7 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
|||
sizeof(*vht), wtbl_tlv,
|
||||
sta_wtbl);
|
||||
vht = (struct wtbl_vht *)tlv;
|
||||
vht->ldpc = ldpc &&
|
||||
vht->ldpc = vht_ldpc &&
|
||||
!!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vht->vht = true;
|
||||
|
||||
|
@ -1004,7 +1013,8 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
|
|||
sta_wtbl, wtbl_hdr);
|
||||
if (info->sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
|
||||
sta_wtbl, wtbl_hdr, true);
|
||||
sta_wtbl, wtbl_hdr,
|
||||
true, true);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
|
||||
|
@ -1044,7 +1054,7 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
if (enable && tx) {
|
||||
u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };
|
||||
static const u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };
|
||||
int i;
|
||||
|
||||
for (i = 7; i > 0; i--) {
|
||||
|
@ -1241,7 +1251,7 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
|
||||
if (he_cap && he_cap->has_he)
|
||||
mode |= PHY_MODE_AX_24G;
|
||||
} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
|
||||
} else if (band == NL80211_BAND_5GHZ) {
|
||||
mode |= PHY_MODE_A;
|
||||
|
||||
if (ht_cap->ht_supported)
|
||||
|
@ -1250,8 +1260,11 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
if (vht_cap->vht_supported)
|
||||
mode |= PHY_MODE_AC;
|
||||
|
||||
if (he_cap && he_cap->has_he && band == NL80211_BAND_5GHZ)
|
||||
if (he_cap && he_cap->has_he)
|
||||
mode |= PHY_MODE_AX_5G;
|
||||
} else if (band == NL80211_BAND_6GHZ) {
|
||||
mode |= PHY_MODE_A | PHY_MODE_AN |
|
||||
PHY_MODE_AC | PHY_MODE_AX_5G;
|
||||
}
|
||||
|
||||
return mode;
|
||||
|
@ -2662,11 +2675,25 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
|
|||
struct bss_info_basic *bss;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));
|
||||
bss = (struct bss_info_basic *)tlv;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (ieee80211_hw_check(phy->hw, SUPPORTS_MULTI_BSSID)) {
|
||||
u8 bssid_id = vif->bss_conf.bssid_indicator;
|
||||
struct wiphy *wiphy = phy->hw->wiphy;
|
||||
|
||||
if (bssid_id > ilog2(wiphy->mbssid_max_interfaces))
|
||||
return -EINVAL;
|
||||
|
||||
bss->non_tx_bssid = vif->bss_conf.bssid_index;
|
||||
bss->max_bssid = bssid_id;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (enable) {
|
||||
rcu_read_lock();
|
||||
|
@ -2691,9 +2718,6 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
|
|||
break;
|
||||
}
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));
|
||||
|
||||
bss = (struct bss_info_basic *)tlv;
|
||||
bss->network_type = cpu_to_le32(type);
|
||||
bss->bmc_wcid_lo = to_wcid_lo(wlan_idx);
|
||||
bss->bmc_wcid_hi = to_wcid_hi(wlan_idx);
|
||||
|
|
|
@ -993,6 +993,7 @@ enum {
|
|||
MCU_UNI_CMD_SUSPEND = 0x05,
|
||||
MCU_UNI_CMD_OFFLOAD = 0x06,
|
||||
MCU_UNI_CMD_HIF_CTRL = 0x07,
|
||||
MCU_UNI_CMD_SNIFFER = 0x24,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -1561,7 +1562,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
|||
u8 rcpi, u8 state);
|
||||
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, void *sta_wtbl,
|
||||
void *wtbl_tlv, bool ldpc);
|
||||
void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc);
|
||||
void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable, bool tx, void *sta_wtbl,
|
||||
|
|
|
@ -245,7 +245,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
|||
usb_set_intfdata(usb_intf, dev);
|
||||
|
||||
mt76x02u_init_mcu(mdev);
|
||||
ret = mt76u_init(mdev, usb_intf, false);
|
||||
ret = mt76u_init(mdev, usb_intf);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static int mt76x2u_probe(struct usb_interface *intf,
|
|||
usb_set_intfdata(intf, dev);
|
||||
|
||||
mt76x02u_init_mcu(mdev);
|
||||
err = mt76u_init(mdev, intf, false);
|
||||
err = mt76u_init(mdev, intf);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -135,9 +135,24 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
|
|||
|
||||
val = eeprom[MT_EE_WIFI_CONF + phy->band_idx];
|
||||
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
|
||||
if (val == MT_EE_BAND_SEL_DEFAULT &&
|
||||
(!is_mt7915(&dev->mt76) || dev->dbdc_support))
|
||||
val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
|
||||
|
||||
if (!is_mt7915(&dev->mt76)) {
|
||||
switch (val) {
|
||||
case MT_EE_V2_BAND_SEL_5GHZ:
|
||||
phy->mt76->cap.has_5ghz = true;
|
||||
return;
|
||||
case MT_EE_V2_BAND_SEL_6GHZ:
|
||||
phy->mt76->cap.has_6ghz = true;
|
||||
return;
|
||||
case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
|
||||
phy->mt76->cap.has_5ghz = true;
|
||||
phy->mt76->cap.has_6ghz = true;
|
||||
return;
|
||||
default:
|
||||
phy->mt76->cap.has_2ghz = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case MT_EE_BAND_SEL_5GHZ:
|
||||
|
@ -248,32 +263,43 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
|||
{
|
||||
u8 *eeprom = dev->mt76.eeprom.data;
|
||||
int index, target_power;
|
||||
bool tssi_on;
|
||||
bool tssi_on, is_7976;
|
||||
|
||||
if (chain_idx > 3)
|
||||
return -EINVAL;
|
||||
|
||||
tssi_on = mt7915_tssi_enabled(dev, chan->band);
|
||||
is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ) {
|
||||
u32 power = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_TX0_POWER_2G : MT_EE_TX0_POWER_2G_V2;
|
||||
if (is_7976) {
|
||||
index = MT_EE_TX0_POWER_2G_V2 + chain_idx;
|
||||
target_power = eeprom[index];
|
||||
} else {
|
||||
index = MT_EE_TX0_POWER_2G + chain_idx * 3;
|
||||
target_power = eeprom[index];
|
||||
|
||||
index = power + chain_idx * 3;
|
||||
target_power = eeprom[index];
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 1];
|
||||
}
|
||||
} else if (chan->band == NL80211_BAND_5GHZ) {
|
||||
int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976);
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 1];
|
||||
if (is_7976) {
|
||||
index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5;
|
||||
target_power = eeprom[index + group];
|
||||
} else {
|
||||
index = MT_EE_TX0_POWER_5G + chain_idx * 12;
|
||||
target_power = eeprom[index + group];
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 8];
|
||||
}
|
||||
} else {
|
||||
int group = mt7915_get_channel_group(chan->hw_value);
|
||||
u32 power = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_TX0_POWER_5G : MT_EE_TX0_POWER_5G_V2;
|
||||
int group = mt7915_get_channel_group_6g(chan->hw_value);
|
||||
|
||||
index = power + chain_idx * 12;
|
||||
target_power = eeprom[index + group];
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 8];
|
||||
index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8;
|
||||
target_power = is_7976 ? eeprom[index + group] : 0;
|
||||
}
|
||||
|
||||
return target_power;
|
||||
|
@ -282,22 +308,20 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
|||
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
|
||||
{
|
||||
u8 *eeprom = dev->mt76.eeprom.data;
|
||||
u32 val;
|
||||
u32 val, offs;
|
||||
s8 delta;
|
||||
u32 rate_2g, rate_5g;
|
||||
|
||||
rate_2g = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_RATE_DELTA_2G : MT_EE_RATE_DELTA_2G_V2;
|
||||
|
||||
rate_5g = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_RATE_DELTA_5G : MT_EE_RATE_DELTA_5G_V2;
|
||||
bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
val = eeprom[rate_2g];
|
||||
offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G;
|
||||
else
|
||||
val = eeprom[rate_5g];
|
||||
offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0;
|
||||
|
||||
if (!(val & MT_EE_RATE_DELTA_EN))
|
||||
val = eeprom[offs];
|
||||
|
||||
if (!offs || !(val & MT_EE_RATE_DELTA_EN))
|
||||
return 0;
|
||||
|
||||
delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
|
||||
|
|
|
@ -25,8 +25,10 @@ enum mt7915_eeprom_field {
|
|||
MT_EE_TX0_POWER_5G = 0x34b,
|
||||
MT_EE_RATE_DELTA_2G_V2 = 0x7d3,
|
||||
MT_EE_RATE_DELTA_5G_V2 = 0x81e,
|
||||
MT_EE_RATE_DELTA_6G_V2 = 0x884, /* 6g fields only appear in eeprom v2 */
|
||||
MT_EE_TX0_POWER_2G_V2 = 0x441,
|
||||
MT_EE_TX0_POWER_5G_V2 = 0x445,
|
||||
MT_EE_TX0_POWER_6G_V2 = 0x465,
|
||||
MT_EE_ADIE_FT_VERSION = 0x9a0,
|
||||
|
||||
__MT_EE_MAX = 0xe00,
|
||||
|
@ -76,6 +78,13 @@ enum mt7915_eeprom_band {
|
|||
MT_EE_BAND_SEL_DUAL,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_EE_V2_BAND_SEL_2GHZ,
|
||||
MT_EE_V2_BAND_SEL_5GHZ,
|
||||
MT_EE_V2_BAND_SEL_6GHZ,
|
||||
MT_EE_V2_BAND_SEL_5GHZ_6GHZ,
|
||||
};
|
||||
|
||||
enum mt7915_sku_rate_group {
|
||||
SKU_CCK,
|
||||
SKU_OFDM,
|
||||
|
@ -96,8 +105,20 @@ enum mt7915_sku_rate_group {
|
|||
};
|
||||
|
||||
static inline int
|
||||
mt7915_get_channel_group(int channel)
|
||||
mt7915_get_channel_group_5g(int channel, bool is_7976)
|
||||
{
|
||||
if (is_7976) {
|
||||
if (channel <= 64)
|
||||
return 0;
|
||||
if (channel <= 96)
|
||||
return 1;
|
||||
if (channel <= 128)
|
||||
return 2;
|
||||
if (channel <= 144)
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (channel >= 184 && channel <= 196)
|
||||
return 0;
|
||||
if (channel <= 48)
|
||||
|
@ -115,6 +136,15 @@ mt7915_get_channel_group(int channel)
|
|||
return 7;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt7915_get_channel_group_6g(int channel)
|
||||
{
|
||||
if (channel <= 29)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_UP(channel - 29, 32);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
|
||||
{
|
||||
|
|
|
@ -312,6 +312,7 @@ mt7915_regd_notifier(struct wiphy *wiphy,
|
|||
|
||||
mt7915_init_txpower(dev, &mphy->sband_2g.sband);
|
||||
mt7915_init_txpower(dev, &mphy->sband_5g.sband);
|
||||
mt7915_init_txpower(dev, &mphy->sband_6g.sband);
|
||||
|
||||
mphy->dfs_state = MT_DFS_STATE_UNKNOWN;
|
||||
mt7915_dfs_init_radar_detector(phy);
|
||||
|
@ -342,6 +343,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
wiphy->reg_notifier = mt7915_regd_notifier;
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
wiphy->mbssid_max_interfaces = 16;
|
||||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
|
@ -359,6 +361,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
|||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
|
@ -558,6 +561,7 @@ static void mt7915_init_work(struct work_struct *work)
|
|||
mt7915_mac_init(dev);
|
||||
mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
|
||||
mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
|
||||
mt7915_init_txpower(dev, &dev->mphy.sband_6g.sband);
|
||||
mt7915_txbf_init(dev);
|
||||
}
|
||||
|
||||
|
@ -579,7 +583,7 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
|
|||
val &= ~MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
/* release wfsys then mcu re-excutes romcode */
|
||||
/* release wfsys then mcu re-executes romcode */
|
||||
val |= MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
|
@ -724,11 +728,18 @@ void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
|
|||
}
|
||||
|
||||
static void
|
||||
mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
|
||||
mt7915_set_stream_he_txbf_caps(struct mt7915_dev *dev,
|
||||
struct ieee80211_sta_he_cap *he_cap,
|
||||
int vif, int nss)
|
||||
{
|
||||
struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
|
||||
u8 c;
|
||||
u8 c, nss_160;
|
||||
|
||||
/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
|
||||
if (is_mt7915(&dev->mt76) && !dev->dbdc_support)
|
||||
nss_160 = nss / 2;
|
||||
else
|
||||
nss_160 = nss;
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (vif == NL80211_IFTYPE_MESH_POINT)
|
||||
|
@ -782,13 +793,21 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
|
|||
/* num_snd_dim
|
||||
* for mt7915, max supported nss is 2 for bw > 80MHz
|
||||
*/
|
||||
c = (nss - 1) |
|
||||
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2;
|
||||
c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
|
||||
nss - 1) |
|
||||
FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,
|
||||
nss_160 - 1);
|
||||
elem->phy_cap_info[5] |= c;
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
|
||||
IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;
|
||||
elem->phy_cap_info[6] |= c;
|
||||
|
||||
if (!is_mt7915(&dev->mt76)) {
|
||||
c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
|
||||
IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
|
||||
elem->phy_cap_info[7] |= c;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -872,7 +891,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
|||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
|
@ -911,7 +930,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
|||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
|
||||
|
||||
|
@ -950,7 +969,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
|||
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map_160);
|
||||
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map_160);
|
||||
|
||||
mt7915_set_stream_he_txbf_caps(he_cap, i, nss);
|
||||
mt7915_set_stream_he_txbf_caps(dev, he_cap, i, nss);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
|
@ -961,6 +980,21 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
|||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_6GHZ) {
|
||||
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
|
||||
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
|
||||
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_8,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
|
||||
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
|
||||
u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
|
||||
|
||||
data[idx].he_6ghz_capa.capa = cpu_to_le16(cap);
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
|
@ -990,6 +1024,15 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
|
|||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_6ghz) {
|
||||
data = phy->iftype[NL80211_BAND_6GHZ];
|
||||
n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);
|
||||
|
||||
band = &phy->mt76->sband_6g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
|
||||
|
|
|
@ -226,8 +226,8 @@ mt7915_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
|||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
|
||||
ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0]));
|
||||
ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1]));
|
||||
ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
|
||||
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
|
||||
ru = (u8)(ru_l | ru_h << 4);
|
||||
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
|
@ -349,14 +349,16 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
|
|||
case MT_PHY_TYPE_HE_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN);
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
|
||||
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
|
@ -400,7 +402,7 @@ static int mt7915_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
|||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) !=
|
||||
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -638,6 +640,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
status->band = mphy->chandef.chan->band;
|
||||
if (status->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (status->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
|
@ -859,7 +863,7 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
u8 snr;
|
||||
int i;
|
||||
|
||||
band_idx = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1]));
|
||||
band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX);
|
||||
if (band_idx && !phy->band_idx)
|
||||
phy = mt7915_ext_phy(dev);
|
||||
|
||||
|
@ -1101,6 +1105,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
|
|||
if (ieee80211_is_beacon(fc)) {
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
|
||||
txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, 0x18));
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
||||
|
@ -1215,8 +1220,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|||
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
||||
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
||||
|
||||
if ((ext_phy || band_idx) &&
|
||||
q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
|
||||
if (ext_phy || band_idx)
|
||||
val |= MT_TXD1_TGID;
|
||||
|
||||
txwi[1] = cpu_to_le32(val);
|
||||
|
@ -1350,10 +1354,10 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
|||
u16 fc, tid;
|
||||
u32 val;
|
||||
|
||||
if (!sta || !sta->ht_cap.ht_supported)
|
||||
if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1]));
|
||||
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
|
||||
if (tid >= 6) /* skip VO queue */
|
||||
return;
|
||||
|
||||
|
@ -1401,7 +1405,7 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
|
|||
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7915_tx_check_aggr(sta, txwi);
|
||||
} else {
|
||||
wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
}
|
||||
|
||||
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
|
||||
|
@ -1435,12 +1439,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
|||
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE,
|
||||
* to the time ack is received or dropped by hw (air + hw queue time).
|
||||
* Should avoid accessing WTBL to get Tx airtime, and use it instead.
|
||||
*/
|
||||
total = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl));
|
||||
total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
|
||||
v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4);
|
||||
if (WARN_ON_ONCE((void *)&free->info[total >> v3] > end))
|
||||
return;
|
||||
|
@ -1558,6 +1557,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
|
|||
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
|
@ -1631,18 +1632,13 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
|
|||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u16 wcidx;
|
||||
u32 txs;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
|
||||
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
|
||||
return;
|
||||
|
||||
txs = le32_to_cpu(txs_data[2]);
|
||||
wcidx = FIELD_GET(MT_TXS2_WCID, txs);
|
||||
|
||||
txs = le32_to_cpu(txs_data[3]);
|
||||
pid = FIELD_GET(MT_TXS3_PID, txs);
|
||||
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
|
||||
pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
|
||||
|
||||
if (pid < MT_PACKET_ID_FIRST)
|
||||
return;
|
||||
|
@ -1679,7 +1675,8 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
|
|||
__le32 *end = (__le32 *)&rxd[len / 4];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7915_mac_tx_free(dev, data, len);
|
||||
|
@ -1704,7 +1701,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
|||
__le32 *end = (__le32 *)&skb->data[skb->len];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
|
@ -1803,7 +1800,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
|||
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
|
||||
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
|
||||
int offset;
|
||||
bool is_5ghz = phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ;
|
||||
bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
|
||||
|
||||
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
|
||||
return;
|
||||
|
@ -1823,7 +1820,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
|||
mt76_wr(dev, MT_TMAC_CDTR(phy->band_idx), cck + reg_offset);
|
||||
mt76_wr(dev, MT_TMAC_ODTR(phy->band_idx), ofdm + reg_offset);
|
||||
mt76_wr(dev, MT_TMAC_ICR0(phy->band_idx),
|
||||
FIELD_PREP(MT_IFS_EIFS_OFDM, is_5ghz ? 84 : 78) |
|
||||
FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) |
|
||||
FIELD_PREP(MT_IFS_RIFS, 2) |
|
||||
FIELD_PREP(MT_IFS_SIFS, 10) |
|
||||
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
|
||||
|
@ -1831,7 +1828,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
|||
mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx),
|
||||
FIELD_PREP(MT_IFS_EIFS_CCK, 314));
|
||||
|
||||
if (phy->slottime < 20 || is_5ghz)
|
||||
if (phy->slottime < 20 || a_band)
|
||||
val = MT7915_CFEND_RATE_DEFAULT;
|
||||
else
|
||||
val = MT7915_CFEND_RATE_11B;
|
||||
|
@ -2190,15 +2187,6 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
|||
cnt = mt76_rr(dev, MT_MIB_SDR31(phy->band_idx));
|
||||
mib->rx_ba_cnt += cnt;
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
|
||||
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK, cnt);
|
||||
|
||||
if (is_mt7915(&dev->mt76))
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx));
|
||||
mib->tx_pkt_ibf_cnt += is_mt7915(&dev->mt76) ?
|
||||
FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK, cnt) :
|
||||
FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDRMUBF(phy->band_idx));
|
||||
mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);
|
||||
|
||||
|
@ -2211,24 +2199,10 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
|||
cnt = mt76_rr(dev, MT_MIB_DR11(phy->band_idx));
|
||||
mib->tx_su_acked_mpdu_cnt += cnt;
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx));
|
||||
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
|
||||
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
|
||||
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
|
||||
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);
|
||||
mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt);
|
||||
mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx));
|
||||
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
|
||||
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
|
||||
cnt = mt76_rr(dev, MT_ETBF_PAR_RPT0(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_PAR_RPT0_FB_BW, cnt);
|
||||
mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NC, cnt);
|
||||
mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NR, cnt);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
|
||||
cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
|
||||
|
@ -2257,6 +2231,26 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
|||
dev->mt76.aggr_stats[aggr1++] += val & 0xffff;
|
||||
dev->mt76.aggr_stats[aggr1++] += val >> 16;
|
||||
}
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
|
||||
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx));
|
||||
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx));
|
||||
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
|
||||
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx));
|
||||
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
|
||||
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
|
||||
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
|
||||
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
|
||||
} else {
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* rts count */
|
||||
|
@ -2285,6 +2279,28 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
|||
dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(15, 0), val);
|
||||
dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(31, 16), val);
|
||||
}
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
|
||||
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt);
|
||||
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt);
|
||||
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt);
|
||||
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR7(phy->band_idx));
|
||||
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_MIB_BFCR7_BFEE_TX_FB_CPL, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR2(phy->band_idx));
|
||||
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_MIB_BFCR2_BFEE_TX_FB_TRIG, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR0(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt);
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR1(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt);
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2364,10 +2380,23 @@ static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy)
|
|||
|
||||
static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain)
|
||||
{
|
||||
int err;
|
||||
int err, region;
|
||||
|
||||
switch (dev->mt76.region) {
|
||||
case NL80211_DFS_ETSI:
|
||||
region = 0;
|
||||
break;
|
||||
case NL80211_DFS_JP:
|
||||
region = 2;
|
||||
break;
|
||||
case NL80211_DFS_FCC:
|
||||
default:
|
||||
region = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain,
|
||||
MT_RX_SEL0, 0);
|
||||
MT_RX_SEL0, region);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -821,8 +821,9 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
|||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
|
||||
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
|
||||
|
||||
if (mvif->cap.ldpc && (elem->phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
if (mvif->cap.he_ldpc &&
|
||||
(elem->phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
cap |= STA_REC_HE_CAP_LDPC;
|
||||
|
||||
if (elem->phy_cap_info[1] &
|
||||
|
@ -986,6 +987,9 @@ mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
|
|||
struct sta_rec_ht *ht;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));
|
||||
|
||||
ht = (struct sta_rec_ht *)tlv;
|
||||
|
@ -1073,7 +1077,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
|||
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
|
||||
wtbl_hdr, mvif->cap.ldpc);
|
||||
wtbl_hdr, mvif->cap.ht_ldpc,
|
||||
mvif->cap.vht_ldpc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1265,6 +1270,9 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
|||
};
|
||||
bool ebf;
|
||||
|
||||
if (!(sta->ht_cap.ht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
ebf = mt7915_is_ebf_supported(phy, vif, sta, false);
|
||||
if (!ebf && !dev->ibf)
|
||||
return;
|
||||
|
@ -1325,6 +1333,9 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
|||
struct tlv *tlv;
|
||||
u8 nrow = 0;
|
||||
|
||||
if (!(sta->vht_cap.vht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
if (!mt7915_is_ebf_supported(phy, vif, sta, true))
|
||||
return;
|
||||
|
||||
|
@ -1582,7 +1593,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
|||
cap |= STA_CAP_TX_STBC;
|
||||
if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
|
||||
cap |= STA_CAP_RX_STBC;
|
||||
if (mvif->cap.ldpc &&
|
||||
if (mvif->cap.ht_ldpc &&
|
||||
(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
|
||||
cap |= STA_CAP_LDPC;
|
||||
|
||||
|
@ -1608,7 +1619,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
|||
cap |= STA_CAP_VHT_TX_STBC;
|
||||
if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
|
||||
cap |= STA_CAP_VHT_RX_STBC;
|
||||
if (mvif->cap.ldpc &&
|
||||
if (mvif->cap.vht_ldpc &&
|
||||
(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
|
||||
cap |= STA_CAP_VHT_LDPC;
|
||||
|
||||
|
@ -1619,6 +1630,10 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
|||
if (sta->he_cap.has_he) {
|
||||
ra->supp_mode |= MODE_HE;
|
||||
cap |= STA_CAP_HE;
|
||||
|
||||
if (sta->he_6ghz_capa.capa)
|
||||
ra->af = le16_get_bits(sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
|
||||
}
|
||||
|
||||
ra->sta_cap = cpu_to_le32(cap);
|
||||
|
@ -1641,7 +1656,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
* once dev->rc_work changes the settings driver should also
|
||||
* update sta_rec_he here.
|
||||
*/
|
||||
if (sta->he_cap.has_he && changed)
|
||||
if (changed)
|
||||
mt7915_mcu_sta_he_tlv(skb, sta, vif);
|
||||
|
||||
/* sta_rec_ra accommodates BW, NSS and only MCS range format
|
||||
|
@ -1710,7 +1725,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
goto out;
|
||||
|
||||
/* tag order is in accordance with firmware dependency. */
|
||||
if (sta && sta->ht_cap.ht_supported) {
|
||||
if (sta) {
|
||||
/* starec bfer */
|
||||
mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta);
|
||||
/* starec ht */
|
||||
|
@ -1727,7 +1742,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (sta && sta->ht_cap.ht_supported) {
|
||||
if (sta) {
|
||||
/* starec amsdu */
|
||||
mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta);
|
||||
/* starec he */
|
||||
|
@ -1810,6 +1825,55 @@ mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
|
|||
info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif, struct bss_info_bcn *bcn,
|
||||
struct ieee80211_mutable_offsets *offs)
|
||||
{
|
||||
struct bss_info_bcn_mbss *mbss;
|
||||
const struct element *elem;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!vif->bss_conf.bssid_indicator)
|
||||
return;
|
||||
|
||||
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID,
|
||||
sizeof(*mbss), &bcn->sub_ntlv,
|
||||
&bcn->len);
|
||||
|
||||
mbss = (struct bss_info_bcn_mbss *)tlv;
|
||||
mbss->offset[0] = cpu_to_le16(offs->tim_offset);
|
||||
mbss->bitmap = cpu_to_le32(1);
|
||||
|
||||
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
|
||||
&skb->data[offs->mbssid_off],
|
||||
skb->len - offs->mbssid_off) {
|
||||
const struct element *sub_elem;
|
||||
|
||||
if (elem->datalen < 2)
|
||||
continue;
|
||||
|
||||
for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
|
||||
const u8 *data;
|
||||
|
||||
if (sub_elem->id || sub_elem->datalen < 4)
|
||||
continue; /* not a valid BSS profile */
|
||||
|
||||
/* Find WLAN_EID_MULTI_BSSID_IDX
|
||||
* in the merged nontransmitted profile
|
||||
*/
|
||||
data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
||||
sub_elem->data,
|
||||
sub_elem->datalen);
|
||||
if (!data || data[1] < 1 || !data[2])
|
||||
continue;
|
||||
|
||||
mbss->offset[data[2]] = cpu_to_le16(data - skb->data);
|
||||
mbss->bitmap |= cpu_to_le32(BIT(data[2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct sk_buff *rskb, struct sk_buff *skb,
|
||||
|
@ -1872,8 +1936,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
len);
|
||||
if (ie && ie[1] >= sizeof(*ht)) {
|
||||
ht = (void *)(ie + 2);
|
||||
vc->ldpc |= !!(le16_to_cpu(ht->cap_info) &
|
||||
IEEE80211_HT_CAP_LDPC_CODING);
|
||||
vc->ht_ldpc = !!(le16_to_cpu(ht->cap_info) &
|
||||
IEEE80211_HT_CAP_LDPC_CODING);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
|
||||
|
@ -1884,7 +1948,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
vht = (void *)(ie + 2);
|
||||
bc = le32_to_cpu(vht->vht_cap_info);
|
||||
|
||||
vc->ldpc |= !!(bc & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vc->vht_ldpc = !!(bc & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vc->vht_su_ebfer =
|
||||
(bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
|
@ -1908,6 +1972,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
|
||||
he = (void *)(ie + 3);
|
||||
|
||||
vc->he_ldpc =
|
||||
HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]);
|
||||
vc->he_su_ebfer =
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) &&
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
|
||||
|
@ -1935,6 +2001,9 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
|||
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
|
||||
if (vif->bss_conf.nontransmitted)
|
||||
return 0;
|
||||
|
||||
rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||
NULL, len);
|
||||
if (IS_ERR(rskb))
|
||||
|
@ -1964,8 +2033,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
|||
|
||||
mt7915_mcu_beacon_check_caps(phy, vif, skb);
|
||||
|
||||
/* TODO: subtag - 11v MBSSID */
|
||||
mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
|
||||
mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
|
||||
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
|
@ -2768,6 +2837,11 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
|
|||
|
||||
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
{
|
||||
static const u8 ch_band[] = {
|
||||
[NL80211_BAND_2GHZ] = 0,
|
||||
[NL80211_BAND_5GHZ] = 1,
|
||||
[NL80211_BAND_6GHZ] = 2,
|
||||
};
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
int freq1 = chandef->center_freq1;
|
||||
|
@ -2795,7 +2869,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
|||
.tx_streams_num = hweight8(phy->mt76->antenna_mask),
|
||||
.rx_streams = phy->mt76->antenna_mask,
|
||||
.band_idx = phy->band_idx,
|
||||
.channel_band = chandef->chan->band,
|
||||
.channel_band = ch_band[chandef->chan->band],
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
|
@ -2811,7 +2885,8 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
|
@ -3457,6 +3532,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
case MT_PHY_TYPE_OFDM:
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ static const u32 mt7915_offs[] = {
|
|||
[PLE_PG_HIF_GROUP] = 0x110,
|
||||
[PLE_HIF_PG_INFO] = 0x114,
|
||||
[AC_OFFSET] = 0x040,
|
||||
[ETBF_PAR_RPT0] = 0x068,
|
||||
};
|
||||
|
||||
static const u32 mt7916_offs[] = {
|
||||
|
@ -194,6 +195,7 @@ static const u32 mt7916_offs[] = {
|
|||
[PLE_PG_HIF_GROUP] = 0x00c,
|
||||
[PLE_HIF_PG_INFO] = 0x388,
|
||||
[AC_OFFSET] = 0x080,
|
||||
[ETBF_PAR_RPT0] = 0x100,
|
||||
};
|
||||
|
||||
static const struct __map mt7915_reg_map[] = {
|
||||
|
|
|
@ -138,7 +138,9 @@ struct mt7915_sta {
|
|||
};
|
||||
|
||||
struct mt7915_vif_cap {
|
||||
bool ldpc:1;
|
||||
bool ht_ldpc:1;
|
||||
bool vht_ldpc:1;
|
||||
bool he_ldpc:1;
|
||||
bool vht_su_ebfer:1;
|
||||
bool vht_su_ebfee:1;
|
||||
bool vht_mu_ebfer:1;
|
||||
|
@ -225,7 +227,7 @@ struct mt7915_phy {
|
|||
struct mt76_phy *mt76;
|
||||
struct mt7915_dev *dev;
|
||||
|
||||
struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES];
|
||||
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
|
||||
|
||||
struct ieee80211_vif *monitor_vif;
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ enum offs_rev {
|
|||
PLE_PG_HIF_GROUP,
|
||||
PLE_HIF_PG_INFO,
|
||||
AC_OFFSET,
|
||||
ETBF_PAR_RPT0,
|
||||
__MT_OFFS_MAX,
|
||||
};
|
||||
|
||||
|
@ -223,10 +224,10 @@ enum offs_rev {
|
|||
#define MT_ETBF_TX_FB_CPL GENMASK(31, 16)
|
||||
#define MT_ETBF_TX_FB_TRI GENMASK(15, 0)
|
||||
|
||||
#define MT_ETBF_RX_FB_CONT(_band) MT_WF_ETBF(_band, 0x068)
|
||||
#define MT_ETBF_RX_FB_BW GENMASK(7, 6)
|
||||
#define MT_ETBF_RX_FB_NC GENMASK(5, 3)
|
||||
#define MT_ETBF_RX_FB_NR GENMASK(2, 0)
|
||||
#define MT_ETBF_PAR_RPT0(_band) MT_WF_ETBF(_band, __OFFS(ETBF_PAR_RPT0))
|
||||
#define MT_ETBF_PAR_RPT0_FB_BW GENMASK(7, 6)
|
||||
#define MT_ETBF_PAR_RPT0_FB_NC GENMASK(5, 3)
|
||||
#define MT_ETBF_PAR_RPT0_FB_NR GENMASK(2, 0)
|
||||
|
||||
#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x0f0)
|
||||
#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16)
|
||||
|
@ -367,11 +368,11 @@ enum offs_rev {
|
|||
#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR31))
|
||||
|
||||
#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR32))
|
||||
#define MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_SDR32_TX_PKT_EBF_CNT GENMASK(15, 0)
|
||||
#define MT_MIB_SDR32_TX_PKT_IBF_CNT GENMASK(31, 16)
|
||||
|
||||
#define MT_MIB_SDR33(_band) MT_WF_MIB(_band, 0x088)
|
||||
#define MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916 GENMASK(31, 16)
|
||||
#define MT_MIB_SDR33_TX_PKT_IBF_CNT GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_SDRMUBF(_band) MT_WF_MIB(_band, __OFFS(MIB_SDRMUBF))
|
||||
#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
|
||||
|
@ -401,6 +402,19 @@ enum offs_rev {
|
|||
((n) << 2))
|
||||
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0))
|
||||
|
||||
#define MT_MIB_BFCR0(_band) MT_WF_MIB(_band, 0x7b0)
|
||||
#define MT_MIB_BFCR0_RX_FB_HT GENMASK(15, 0)
|
||||
#define MT_MIB_BFCR0_RX_FB_VHT GENMASK(31, 16)
|
||||
|
||||
#define MT_MIB_BFCR1(_band) MT_WF_MIB(_band, 0x7b4)
|
||||
#define MT_MIB_BFCR1_RX_FB_HE GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_BFCR2(_band) MT_WF_MIB(_band, 0x7b8)
|
||||
#define MT_MIB_BFCR2_BFEE_TX_FB_TRIG GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_BFCR7(_band) MT_WF_MIB(_band, 0x7cc)
|
||||
#define MT_MIB_BFCR7_BFEE_TX_FB_CPL GENMASK(15, 0)
|
||||
|
||||
/* WTBLON TOP */
|
||||
#define MT_WTBLON_TOP_BASE 0x820d4000
|
||||
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
|
||||
|
|
|
@ -196,6 +196,8 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
|
|||
|
||||
type = mt7986_wmac_check_adie_type(dev);
|
||||
pinctrl = devm_pinctrl_get(dev->mt76.dev);
|
||||
if (IS_ERR(pinctrl))
|
||||
return PTR_ERR(pinctrl);
|
||||
|
||||
switch (type) {
|
||||
case ADIE_SB:
|
||||
|
|
|
@ -271,6 +271,8 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
|
|||
case MT76_TM_TX_MODE_OFDM:
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
|
@ -572,6 +574,8 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
|
|||
|
||||
if (chandef->chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &phy->mt76->sband_5g.sband;
|
||||
else if (chandef->chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &phy->mt76->sband_6g.sband;
|
||||
else
|
||||
sband = &phy->mt76->sband_2g.sband;
|
||||
|
||||
|
|
|
@ -24,3 +24,14 @@ config MT7921S
|
|||
This adds support for MT7921S 802.11ax 2x2:2SS wireless devices.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config MT7921U
|
||||
tristate "MediaTek MT7921U (USB) support"
|
||||
select MT76_USB
|
||||
select MT7921_COMMON
|
||||
depends on MAC80211
|
||||
depends on USB
|
||||
help
|
||||
This adds support for MT7921U 802.11ax 2x2:2SS wireless devices.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
obj-$(CONFIG_MT7921_COMMON) += mt7921-common.o
|
||||
obj-$(CONFIG_MT7921E) += mt7921e.o
|
||||
obj-$(CONFIG_MT7921S) += mt7921s.o
|
||||
obj-$(CONFIG_MT7921U) += mt7921u.o
|
||||
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
|
@ -10,3 +11,4 @@ mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o
|
|||
mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o
|
||||
mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o
|
||||
mt7921u-y := usb.o usb_mac.o
|
||||
|
|
|
@ -129,23 +129,22 @@ mt7921_queues_acq(struct seq_file *s, void *data)
|
|||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
int j, acs = i / 4, index = i % 4;
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 ctrl, val, qlen = 0;
|
||||
int j;
|
||||
|
||||
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
|
||||
ctrl = BIT(31) | BIT(15) | (acs << 8);
|
||||
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
|
||||
ctrl = BIT(31) | BIT(11) | (i << 24);
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (val & BIT(j))
|
||||
continue;
|
||||
|
||||
mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
|
||||
ctrl | (j + (index << 5)));
|
||||
mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
|
||||
qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
|
||||
GENMASK(11, 0));
|
||||
}
|
||||
seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
|
||||
seq_printf(s, "AC%d: queued=%d\n", i, qlen);
|
||||
}
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
|
@ -268,6 +267,9 @@ mt7921_pm_set(void *data, u64 val)
|
|||
struct mt7921_dev *dev = data;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
if (mt76_is_usb(&dev->mt76))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
if (val == pm->enable_user)
|
||||
|
@ -312,6 +314,9 @@ mt7921_deep_sleep_set(void *data, u64 val)
|
|||
bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
bool enable = !!val;
|
||||
|
||||
if (mt76_is_usb(&dev->mt76))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
if (pm->ds_enable_user == enable)
|
||||
goto out;
|
||||
|
@ -429,8 +434,13 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
|
|||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
|
||||
mt7921_queues_read);
|
||||
if (mt76_is_mmio(&dev->mt76))
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
dir, mt7921_queues_read);
|
||||
else
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
dir, mt76_queues_read);
|
||||
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
|
||||
mt7921_queues_acq);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
|
||||
static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ out:
|
|||
|
||||
static int mt7921_init_hardware(struct mt7921_dev *dev)
|
||||
{
|
||||
int ret, idx, i;
|
||||
int ret, i;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
|
||||
|
@ -182,6 +182,13 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7921_init_wcid(struct mt7921_dev *dev)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Beacon and mgmt frames should occupy wcid 0 */
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
|
||||
if (idx)
|
||||
|
@ -195,6 +202,38 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void mt7921_init_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
|
||||
init_work);
|
||||
int ret;
|
||||
|
||||
ret = mt7921_init_hardware(dev);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
mt76_set_stream_caps(&dev->mphy, true);
|
||||
mt7921_set_stream_he_caps(&dev->phy);
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "register device failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mt7921_init_debugfs(dev);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "register debugfs failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* we support chip reset now */
|
||||
dev->hw_init_done = true;
|
||||
|
||||
mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
|
||||
}
|
||||
|
||||
int mt7921_register_device(struct mt7921_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
|
@ -222,19 +261,22 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
|||
spin_lock_init(&dev->sta_poll_lock);
|
||||
|
||||
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
|
||||
INIT_WORK(&dev->init_work, mt7921_init_work);
|
||||
|
||||
dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
|
||||
dev->pm.stats.last_wake_event = jiffies;
|
||||
dev->pm.stats.last_doze_event = jiffies;
|
||||
dev->pm.enable_user = true;
|
||||
dev->pm.enable = true;
|
||||
dev->pm.ds_enable_user = true;
|
||||
dev->pm.ds_enable = true;
|
||||
if (!mt76_is_usb(&dev->mt76)) {
|
||||
dev->pm.enable_user = true;
|
||||
dev->pm.enable = true;
|
||||
dev->pm.ds_enable_user = true;
|
||||
dev->pm.ds_enable = true;
|
||||
}
|
||||
|
||||
if (mt76_is_sdio(&dev->mt76))
|
||||
if (!mt76_is_mmio(&dev->mt76))
|
||||
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
|
||||
ret = mt7921_init_hardware(dev);
|
||||
ret = mt7921_init_wcid(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -262,23 +304,7 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
|||
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
|
||||
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
|
||||
|
||||
mt76_set_stream_caps(&dev->mphy, true);
|
||||
mt7921_set_stream_he_caps(&dev->phy);
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7921_init_debugfs(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->hw_init_done = true;
|
||||
queue_work(system_wq, &dev->init_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -176,8 +176,8 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
|||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
|
||||
ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0]));
|
||||
ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1]));
|
||||
ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
|
||||
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
|
||||
ru = (u8)(ru_l | ru_h << 4);
|
||||
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
|
@ -247,19 +247,19 @@ mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
|
|||
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
|
||||
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
|
||||
|
||||
he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, le32_to_cpu(rxv[3]));
|
||||
he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_40) {
|
||||
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
|
||||
he_mu->ru_ch2[0] =
|
||||
FIELD_GET(MT_CRXV_HE_RU1, le32_to_cpu(rxv[3]));
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
|
||||
}
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_80) {
|
||||
he_mu->ru_ch1[1] =
|
||||
FIELD_GET(MT_CRXV_HE_RU2, le32_to_cpu(rxv[3]));
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
|
||||
he_mu->ru_ch2[1] =
|
||||
FIELD_GET(MT_CRXV_HE_RU3, le32_to_cpu(rxv[3]));
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,14 +304,16 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
|
|||
case MT_PHY_TYPE_HE_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN);
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
|
||||
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
|
@ -409,7 +411,7 @@ static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
|||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) !=
|
||||
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1024,7 +1026,7 @@ void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
|||
if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1]));
|
||||
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
|
||||
if (tid >= 6) /* skip VO queue */
|
||||
return;
|
||||
|
||||
|
@ -1163,18 +1165,13 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
|
|||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u16 wcidx;
|
||||
u32 txs;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
|
||||
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
|
||||
return;
|
||||
|
||||
txs = le32_to_cpu(txs_data[2]);
|
||||
wcidx = FIELD_GET(MT_TXS2_WCID, txs);
|
||||
|
||||
txs = le32_to_cpu(txs_data[3]);
|
||||
pid = FIELD_GET(MT_TXS3_PID, txs);
|
||||
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
|
||||
pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
|
||||
|
||||
if (pid < MT_PACKET_ID_FIRST)
|
||||
return;
|
||||
|
@ -1213,8 +1210,8 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
|||
enum rx_pkt_type type;
|
||||
u16 flag;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);
|
||||
|
||||
if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
|
||||
type = PKT_TYPE_NORMAL_MCU;
|
||||
|
@ -1627,3 +1624,94 @@ void mt7921_coredump_work(struct work_struct *work)
|
|||
|
||||
mt7921_reset(&dev->mt76);
|
||||
}
|
||||
|
||||
/* usb_sdio */
|
||||
static void
|
||||
mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
|
||||
enum mt76_txq_id qid, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
|
||||
|
||||
memset(txwi, 0, MT_SDIO_TXD_SIZE);
|
||||
mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
|
||||
skb_push(skb, MT_SDIO_TXD_SIZE);
|
||||
}
|
||||
|
||||
int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_tx_info *tx_info)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct sk_buff *skb = tx_info->skb;
|
||||
int err, pad, pktid, type;
|
||||
|
||||
if (unlikely(tx_info->skb->len <= ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (!wcid)
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
if (sta) {
|
||||
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
|
||||
|
||||
if (time_after(jiffies, msta->last_txs + HZ / 4)) {
|
||||
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
msta->last_txs = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
|
||||
mt7921_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
|
||||
|
||||
type = mt76_is_sdio(mdev) ? MT7921_SDIO_DATA : 0;
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
if (mt76_is_usb(mdev))
|
||||
pad += 4;
|
||||
|
||||
err = mt76_skb_adjust_pad(skb, pad);
|
||||
if (err)
|
||||
/* Release pktid in case of error. */
|
||||
idr_remove(&wcid->pktid, pktid);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_prepare_skb);
|
||||
|
||||
void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE);
|
||||
unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
u16 idx;
|
||||
|
||||
idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid = rcu_dereference(mdev->wcid[idx]);
|
||||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7921_tx_check_aggr(sta, txwi);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb);
|
||||
|
||||
bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_mac_sta_poll(dev);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data);
|
||||
|
|
|
@ -202,6 +202,7 @@ enum tx_mcu_port_q_idx {
|
|||
#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
|
||||
#define MT_SDIO_TAIL_SIZE 8
|
||||
#define MT_SDIO_HDR_SIZE 4
|
||||
#define MT_USB_TAIL_SIZE 4
|
||||
|
||||
#define MT_TXD0_Q_IDX GENMASK(31, 25)
|
||||
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
|
||||
|
|
|
@ -264,7 +264,7 @@ static int mt7921_start(struct ieee80211_hw *hw)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void mt7921_stop(struct ieee80211_hw *hw)
|
||||
void mt7921_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
|
@ -281,6 +281,7 @@ static void mt7921_stop(struct ieee80211_hw *hw)
|
|||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_stop);
|
||||
|
||||
static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
|
@ -479,9 +480,27 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
|||
mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_dev *dev = priv;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
mt7921_mcu_set_sniffer(dev, vif, monitor);
|
||||
pm->enable = !monitor;
|
||||
pm->ds_enable = !monitor;
|
||||
|
||||
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
|
||||
|
||||
if (monitor)
|
||||
mt7921_mcu_set_beacon_filter(dev, vif, false);
|
||||
}
|
||||
|
||||
void mt7921_set_runtime_pm(struct mt7921_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev->mphy.hw;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
|
@ -516,17 +535,10 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
|||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
||||
bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
if (!enabled)
|
||||
phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
|
||||
else
|
||||
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
|
||||
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN,
|
||||
enabled);
|
||||
mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
|
||||
mt7921_set_runtime_pm(dev);
|
||||
ieee80211_iterate_active_interfaces(hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_sniffer_interface_iter, dev);
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0));
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -863,7 +863,8 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
|
|||
else
|
||||
req.channel_band = chandef->chan->band;
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
|
@ -1135,3 +1136,33 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct {
|
||||
struct {
|
||||
u8 band_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct sniffer_enable_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 enable;
|
||||
u8 pad[3];
|
||||
} __packed enable;
|
||||
} req = {
|
||||
.hdr = {
|
||||
.band_idx = mvif->band_idx,
|
||||
},
|
||||
.enable = {
|
||||
.tag = cpu_to_le16(0),
|
||||
.len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)),
|
||||
.enable = enable,
|
||||
},
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),
|
||||
true);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#define MT7921_DRV_OWN_RETRY_COUNT 10
|
||||
#define MT7921_MCU_INIT_RETRY_COUNT 10
|
||||
#define MT7921_WFSYS_INIT_RETRY_COUNT 2
|
||||
|
||||
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
|
||||
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
|
||||
|
@ -204,6 +205,8 @@ struct mt7921_dev {
|
|||
struct list_head sta_poll_list;
|
||||
spinlock_t sta_poll_lock;
|
||||
|
||||
struct work_struct init_work;
|
||||
|
||||
u8 fw_debug;
|
||||
|
||||
struct mt76_connac_pm pm;
|
||||
|
@ -352,17 +355,20 @@ static inline void mt7921_mcu_tx_cleanup(struct mt7921_dev *dev)
|
|||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false);
|
||||
}
|
||||
|
||||
static inline void mt7921_skb_add_sdio_hdr(struct sk_buff *skb,
|
||||
enum mt7921_sdio_pkt_type type)
|
||||
static inline void
|
||||
mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb,
|
||||
int type)
|
||||
{
|
||||
u32 hdr;
|
||||
u32 hdr, len;
|
||||
|
||||
hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, skb->len + sizeof(hdr)) |
|
||||
len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr);
|
||||
hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, len) |
|
||||
FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type);
|
||||
|
||||
put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr)));
|
||||
}
|
||||
|
||||
void mt7921_stop(struct ieee80211_hw *hw);
|
||||
int mt7921_mac_init(struct mt7921_dev *dev);
|
||||
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
|
||||
void mt7921_mac_reset_counters(struct mt7921_phy *phy);
|
||||
|
@ -384,7 +390,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
|
||||
void mt7921_tx_worker(struct mt76_worker *w);
|
||||
void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc);
|
||||
void mt7921_tx_token_put(struct mt7921_dev *dev);
|
||||
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb);
|
||||
|
@ -409,7 +414,6 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
|
|||
int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
||||
void mt7921_pm_wake_work(struct work_struct *work);
|
||||
void mt7921_pm_power_save_work(struct work_struct *work);
|
||||
bool mt7921_wait_for_mcu_init(struct mt7921_dev *dev);
|
||||
void mt7921_coredump_work(struct work_struct *work);
|
||||
int mt7921_wfsys_reset(struct mt7921_dev *dev);
|
||||
int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr);
|
||||
|
@ -444,12 +448,26 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
|||
int mt7921s_mcu_init(struct mt7921_dev *dev);
|
||||
int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev);
|
||||
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
||||
int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_tx_info *tx_info);
|
||||
void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
||||
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data);
|
||||
void mt7921_set_runtime_pm(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
|
||||
int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_tx_info *tx_info);
|
||||
void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e);
|
||||
bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
||||
|
||||
/* usb */
|
||||
#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f)
|
||||
#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e)
|
||||
|
||||
int mt7921u_mcu_power_on(struct mt7921_dev *dev);
|
||||
int mt7921u_wfsys_reset(struct mt7921_dev *dev);
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev);
|
||||
int mt7921u_init_reset(struct mt7921_dev *dev);
|
||||
int mt7921u_mac_reset(struct mt7921_dev *dev);
|
||||
#endif
|
||||
|
|
|
@ -105,6 +105,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
|
|||
int i;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
|
|
|
@ -137,7 +137,7 @@ mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
|
|||
|
||||
wcid_idx = wcid->idx;
|
||||
} else {
|
||||
wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
}
|
||||
|
||||
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
|
||||
|
@ -164,11 +164,7 @@ mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
|
|||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
|
||||
|
||||
/* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE,
|
||||
* to the time ack is received or dropped by hw (air + hw queue time).
|
||||
* Should avoid accessing WTBL to get Tx airtime, and use it instead.
|
||||
*/
|
||||
count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl));
|
||||
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
|
||||
if (WARN_ON_ONCE((void *)&free->info[count] > end))
|
||||
return;
|
||||
|
||||
|
@ -231,7 +227,8 @@ bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len)
|
|||
__le32 *end = (__le32 *)&rxd[len / 4];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7921e_mac_tx_free(dev, data, len);
|
||||
|
@ -252,7 +249,7 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
|||
__le32 *rxd = (__le32 *)skb->data;
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
|
|
|
@ -17,13 +17,12 @@
|
|||
#define MT_PLE_BASE 0x820c0000
|
||||
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
|
||||
|
||||
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0)
|
||||
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4)
|
||||
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8)
|
||||
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc)
|
||||
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0)
|
||||
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4)
|
||||
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8)
|
||||
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec)
|
||||
|
||||
#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \
|
||||
((n) << 2))
|
||||
#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
|
||||
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
|
||||
|
||||
#define MT_MDP_BASE 0x820cd000
|
||||
|
@ -354,6 +353,7 @@
|
|||
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
|
||||
#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3)
|
||||
#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6)
|
||||
#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9)
|
||||
#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
|
||||
#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
|
||||
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
|
||||
|
@ -378,6 +378,9 @@
|
|||
#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640)
|
||||
#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644)
|
||||
|
||||
#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0)
|
||||
#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16)
|
||||
|
||||
#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680)
|
||||
#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684)
|
||||
#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688)
|
||||
|
@ -426,6 +429,10 @@
|
|||
#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120)
|
||||
#define MT_WFDMA_NEED_REINIT BIT(1)
|
||||
|
||||
#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs))
|
||||
#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
|
||||
#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
|
||||
|
||||
#define MT_HW_BOUND 0x70010020
|
||||
#define MT_HW_CHIPID 0x70010200
|
||||
#define MT_HW_REV 0x70010204
|
||||
|
@ -434,12 +441,14 @@
|
|||
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
|
||||
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
|
||||
|
||||
#define MT_DMA_SHDL(ofs) (0xd6000 + (ofs))
|
||||
#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs))
|
||||
#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004)
|
||||
#define MT_DMASHDL_DMASHDL_BYPASS BIT(28)
|
||||
#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008)
|
||||
#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c)
|
||||
#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16)
|
||||
#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010)
|
||||
#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16)
|
||||
#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c)
|
||||
#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0)
|
||||
#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16)
|
||||
|
@ -454,6 +463,43 @@
|
|||
|
||||
#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2))
|
||||
|
||||
#define MT_WFDMA_HOST_CONFIG 0x7c027030
|
||||
#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6)
|
||||
|
||||
#define MT_UMAC(ofs) (0x74000000 + (ofs))
|
||||
#define MT_UDMA_TX_QSEL MT_UMAC(0x008)
|
||||
#define MT_FW_DL_EN BIT(3)
|
||||
|
||||
#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c)
|
||||
#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0)
|
||||
#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8)
|
||||
|
||||
#define MT_UDMA_WLCFG_0 MT_UMAC(0x18)
|
||||
#define MT_WL_RX_AGG_TO GENMASK(7, 0)
|
||||
#define MT_WL_RX_AGG_LMT GENMASK(15, 8)
|
||||
#define MT_WL_TX_TMOUT_FUNC_EN BIT(16)
|
||||
#define MT_WL_TX_DPH_CHK_EN BIT(17)
|
||||
#define MT_WL_RX_MPSZ_PAD0 BIT(18)
|
||||
#define MT_WL_RX_FLUSH BIT(19)
|
||||
#define MT_TICK_1US_EN BIT(20)
|
||||
#define MT_WL_RX_AGG_EN BIT(21)
|
||||
#define MT_WL_RX_EN BIT(22)
|
||||
#define MT_WL_TX_EN BIT(23)
|
||||
#define MT_WL_RX_BUSY BIT(30)
|
||||
#define MT_WL_TX_BUSY BIT(31)
|
||||
|
||||
#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20)
|
||||
#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22)
|
||||
#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24)
|
||||
|
||||
#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs))
|
||||
#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090)
|
||||
|
||||
#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs))
|
||||
#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208)
|
||||
#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0)
|
||||
#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2))
|
||||
|
||||
#define MT_CONN_STATUS 0x7c053c10
|
||||
#define MT_WIFI_PATCH_DL_STATE BIT(0)
|
||||
|
||||
|
@ -467,6 +513,7 @@
|
|||
#define WFSYS_SW_INIT_DONE BIT(4)
|
||||
|
||||
#define MT_CONN_ON_MISC 0x7c0600f0
|
||||
#define MT_TOP_MISC2_FW_PWR_ON BIT(0)
|
||||
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@ static void mt7921s_unregister_device(struct mt7921_dev *dev)
|
|||
{
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
|
@ -91,9 +92,9 @@ static int mt7921s_probe(struct sdio_func *func,
|
|||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.tx_prepare_skb = mt7921s_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921s_tx_complete_skb,
|
||||
.tx_status_data = mt7921s_tx_status_data,
|
||||
.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
|
||||
.tx_status_data = mt7921_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
|
|
|
@ -140,86 +140,3 @@ out:
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
|
||||
enum mt76_txq_id qid, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
|
||||
|
||||
memset(txwi, 0, MT_SDIO_TXD_SIZE);
|
||||
mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
|
||||
skb_push(skb, MT_SDIO_TXD_SIZE);
|
||||
}
|
||||
|
||||
int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_tx_info *tx_info)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct sk_buff *skb = tx_info->skb;
|
||||
int err, pad, pktid;
|
||||
|
||||
if (unlikely(tx_info->skb->len <= ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (!wcid)
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
if (sta) {
|
||||
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
|
||||
|
||||
if (time_after(jiffies, msta->last_txs + HZ / 4)) {
|
||||
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
msta->last_txs = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
|
||||
mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
|
||||
|
||||
mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
|
||||
err = mt76_skb_adjust_pad(skb, pad);
|
||||
if (err)
|
||||
/* Release pktid in case of error. */
|
||||
idr_remove(&wcid->pktid, pktid);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE);
|
||||
unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
u16 idx;
|
||||
|
||||
idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
|
||||
wcid = rcu_dereference(mdev->wcid[idx]);
|
||||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7921_tx_check_aggr(sta, txwi);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
|
||||
bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_mac_sta_poll(dev);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
|||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
type = MT7921_SDIO_FWDL;
|
||||
|
||||
mt7921_skb_add_sdio_hdr(skb, type);
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
__skb_put_zero(skb, pad);
|
||||
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2022 MediaTek Inc.
|
||||
*
|
||||
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
static const struct usb_device_id mt7921u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff) },
|
||||
{ },
|
||||
};
|
||||
|
||||
static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask;
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt7921u_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int ret, i = 0, batch_len;
|
||||
const u8 *val = data;
|
||||
|
||||
len = round_up(len, 4);
|
||||
|
||||
mutex_lock(&usb->usb_ctrl_mtx);
|
||||
while (i < len) {
|
||||
batch_len = min_t(int, usb->data_len, len - i);
|
||||
memcpy(usb->data, val + i, batch_len);
|
||||
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
|
||||
(offset + i) >> 16, offset + i,
|
||||
usb->data, batch_len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
i += batch_len;
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
int mt7921u_mcu_power_on(struct mt7921_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
|
||||
MT_TOP_MISC2_FW_PWR_ON, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *seq)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
u32 pad, ep;
|
||||
int ret;
|
||||
|
||||
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cmd != MCU_CMD(FW_SCATTER))
|
||||
ep = MT_EP_OUT_INBAND_CMD;
|
||||
else
|
||||
ep = MT_EP_OUT_AC_BE;
|
||||
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, 0);
|
||||
pad = round_up(skb->len, 4) + 4 - skb->len;
|
||||
__skb_put_zero(skb, pad);
|
||||
|
||||
ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
|
||||
1000, ep);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7921u_mcu_init(struct mt7921_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mcu_ops = {
|
||||
.headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd),
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7921u_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
|
||||
dev->mt76.mcu_ops = &mcu_ops;
|
||||
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
ret = mt7921_run_firmware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
|
||||
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7921u_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
mt7921_stop(hw);
|
||||
}
|
||||
|
||||
static void mt7921u_cleanup(struct mt7921_dev *dev)
|
||||
{
|
||||
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
mt7921u_wfsys_reset(dev);
|
||||
mt7921_mcu_exit(dev);
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
}
|
||||
|
||||
static int mt7921u_probe(struct usb_interface *usb_intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.txwi_size = MT_SDIO_TXD_SIZE,
|
||||
.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
|
||||
.tx_status_data = mt7921_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
.sta_assoc = mt7921_mac_sta_assoc,
|
||||
.sta_remove = mt7921_mac_sta_remove,
|
||||
.update_survey = mt7921_update_channel,
|
||||
};
|
||||
static const struct mt7921_hif_ops hif_ops = {
|
||||
.mcu_init = mt7921u_mcu_init,
|
||||
.init_reset = mt7921u_init_reset,
|
||||
.reset = mt7921u_mac_reset,
|
||||
};
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt7921u_rr,
|
||||
.wr = mt7921u_wr,
|
||||
.rmw = mt7921u_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt7921u_copy,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(usb_intf);
|
||||
struct ieee80211_ops *ops;
|
||||
struct ieee80211_hw *hw;
|
||||
struct mt7921_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
int ret;
|
||||
|
||||
ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops),
|
||||
GFP_KERNEL);
|
||||
if (!ops)
|
||||
return -ENOMEM;
|
||||
|
||||
ops->stop = mt7921u_stop;
|
||||
|
||||
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
dev->hif_ops = &hif_ops;
|
||||
|
||||
udev = usb_get_dev(udev);
|
||||
usb_reset_device(udev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
||||
ret = __mt76u_init(mdev, usb_intf, &bus_ops);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
|
||||
ret = mt7921u_wfsys_reset(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = mt7921u_mcu_power_on(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt76u_alloc_mcu_queue(&dev->mt76);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt76u_alloc_queues(&dev->mt76);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt7921u_dma_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hw = mt76_hw(dev);
|
||||
/* check hw sg support in order to enable AMSDU */
|
||||
hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
|
||||
|
||||
ret = mt7921_register_device(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7921u_disconnect(struct usb_interface *usb_intf)
|
||||
{
|
||||
struct mt7921_dev *dev = usb_get_intfdata(usb_intf);
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return;
|
||||
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt7921u_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
|
||||
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7921_ROM_PATCH);
|
||||
|
||||
static struct usb_driver mt7921u_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = mt7921u_device_table,
|
||||
.probe = mt7921u_probe,
|
||||
.disconnect = mt7921u_disconnect,
|
||||
.soft_unbind = 1,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
module_usb_driver(mt7921u_driver);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,252 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2022 MediaTek Inc.
|
||||
*
|
||||
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE,
|
||||
USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE,
|
||||
USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt7921u_dma_prefetch(struct mt7921_dev *dev)
|
||||
{
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x80);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0xc0);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x100);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x140);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x180);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x280);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x2c0);
|
||||
}
|
||||
|
||||
static void mt7921u_wfdma_init(struct mt7921_dev *dev)
|
||||
{
|
||||
mt7921u_dma_prefetch(dev);
|
||||
|
||||
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO);
|
||||
mt76_set(dev, MT_UWFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
|
||||
MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL |
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
/* disable dmashdl */
|
||||
mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0,
|
||||
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
|
||||
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
|
||||
|
||||
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
}
|
||||
|
||||
static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev)
|
||||
{
|
||||
if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN);
|
||||
mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* usb endpoint reset opt
|
||||
* bits[4,9]: out blk ep 4-9
|
||||
* bits[20,21]: in blk ep 4-5
|
||||
* bits[22]: in int ep 6
|
||||
*/
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT);
|
||||
if (reset)
|
||||
val |= GENMASK(9, 4) | GENMASK(22, 20);
|
||||
else
|
||||
val &= ~(GENMASK(9, 4) | GENMASK(22, 20));
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
|
||||
}
|
||||
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt7921u_wfdma_init(dev);
|
||||
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
|
||||
|
||||
mt76_set(dev, MT_UDMA_WLCFG_0,
|
||||
MT_WL_RX_EN | MT_WL_TX_EN |
|
||||
MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN);
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_0,
|
||||
MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
|
||||
|
||||
err = mt7921u_dma_rx_evt_ep4(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt7921u_epctl_rst_opt(dev, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921u_wfsys_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
mt7921u_epctl_rst_opt(dev, false);
|
||||
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
|
||||
val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
|
||||
val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
|
||||
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
|
||||
for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) {
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
|
||||
if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
|
||||
break;
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (i == MT7921_WFSYS_INIT_RETRY_COUNT)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921u_init_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
mt7921_mcu_exit(dev);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
mt7921u_wfsys_reset(dev);
|
||||
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
return mt76u_resume_rx(&dev->mt76);
|
||||
}
|
||||
|
||||
int mt7921u_mac_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
mt7921_mcu_exit(dev);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
mt7921u_wfsys_reset(dev);
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
err = mt76u_resume_rx(&dev->mt76);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921u_mcu_power_on(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921u_dma_init(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
err = mt7921_run_firmware(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
err = mt7921_mcu_set_eeprom(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921_mac_init(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = __mt7921_start(&dev->phy);
|
||||
out:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
|
||||
return err;
|
||||
}
|
|
@ -118,7 +118,7 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
|
|||
__le32 *rxd = (__le32 *)buf;
|
||||
|
||||
/* parse rxd to get the actual packet length */
|
||||
len = FIELD_GET(GENMASK(15, 0), le32_to_cpu(rxd[0]));
|
||||
len = le32_get_bits(rxd[0], GENMASK(15, 0));
|
||||
e->skb = mt76s_build_rx_skb(buf, len, round_up(len + 4, 4));
|
||||
if (!e->skb)
|
||||
break;
|
||||
|
|
|
@ -15,9 +15,8 @@ static bool disable_usb_sg;
|
|||
module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support");
|
||||
|
||||
static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
u8 req_type, u16 val, u16 offset,
|
||||
void *buf, size_t len)
|
||||
int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u16 val, u16 offset, void *buf, size_t len)
|
||||
{
|
||||
struct usb_interface *uintf = to_usb_interface(dev->dev);
|
||||
struct usb_device *udev = interface_to_usbdev(uintf);
|
||||
|
@ -45,6 +44,7 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
|||
req, offset, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt76u_vendor_request);
|
||||
|
||||
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
u8 req_type, u16 val, u16 offset,
|
||||
|
@ -62,22 +62,21 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76u_vendor_request);
|
||||
|
||||
static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr)
|
||||
u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
u32 data = ~0;
|
||||
int ret;
|
||||
|
||||
ret = __mt76u_vendor_request(dev, req,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
addr >> 16, addr, usb->data,
|
||||
sizeof(__le32));
|
||||
ret = __mt76u_vendor_request(dev, req, req_type, addr >> 16,
|
||||
addr, usb->data, sizeof(__le32));
|
||||
if (ret == sizeof(__le32))
|
||||
data = get_unaligned_le32(usb->data);
|
||||
trace_usb_reg_rr(dev, addr, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(___mt76u_rr);
|
||||
|
||||
static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
|
@ -95,7 +94,8 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr)
|
|||
break;
|
||||
}
|
||||
|
||||
return ___mt76u_rr(dev, req, addr & ~MT_VEND_TYPE_MASK);
|
||||
return ___mt76u_rr(dev, req, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
addr & ~MT_VEND_TYPE_MASK);
|
||||
}
|
||||
|
||||
static u32 mt76u_rr(struct mt76_dev *dev, u32 addr)
|
||||
|
@ -109,29 +109,17 @@ static u32 mt76u_rr(struct mt76_dev *dev, u32 addr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ___mt76u_wr(struct mt76_dev *dev, u8 req,
|
||||
u32 addr, u32 val)
|
||||
void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u32 addr, u32 val)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
|
||||
put_unaligned_le32(val, usb->data);
|
||||
__mt76u_vendor_request(dev, req,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
addr >> 16, addr, usb->data,
|
||||
sizeof(__le32));
|
||||
__mt76u_vendor_request(dev, req, req_type, addr >> 16,
|
||||
addr, usb->data, sizeof(__le32));
|
||||
trace_usb_reg_wr(dev, addr, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(___mt76u_wr);
|
||||
|
||||
static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
|
@ -145,7 +133,8 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
|||
req = MT_VEND_MULTI_WRITE;
|
||||
break;
|
||||
}
|
||||
___mt76u_wr(dev, req, addr & ~MT_VEND_TYPE_MASK, val);
|
||||
___mt76u_wr(dev, req, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
addr & ~MT_VEND_TYPE_MASK, val);
|
||||
}
|
||||
|
||||
static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
|
@ -155,13 +144,6 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
|||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
|
@ -173,17 +155,6 @@ static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr,
|
|||
return val;
|
||||
}
|
||||
|
||||
static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, addr) & ~mask;
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt76u_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
|
@ -216,33 +187,8 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
|
|||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt76u_copy_ext(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int ret, i = 0, batch_len;
|
||||
const u8 *val = data;
|
||||
|
||||
len = round_up(len, 4);
|
||||
mutex_lock(&usb->usb_ctrl_mtx);
|
||||
while (i < len) {
|
||||
batch_len = min_t(int, usb->data_len, len - i);
|
||||
memcpy(usb->data, val + i, batch_len);
|
||||
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
(offset + i) >> 16, offset + i,
|
||||
usb->data, batch_len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
i += batch_len;
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len)
|
||||
void mt76u_read_copy(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int i = 0, batch_len, ret;
|
||||
|
@ -264,6 +210,7 @@ mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset,
|
|||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76u_read_copy);
|
||||
|
||||
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
|
||||
const u16 offset, const u32 val)
|
||||
|
@ -1112,24 +1059,13 @@ static const struct mt76_queue_ops usb_queue_ops = {
|
|||
.kick = mt76u_tx_kick,
|
||||
};
|
||||
|
||||
int mt76u_init(struct mt76_dev *dev,
|
||||
struct usb_interface *intf, bool ext)
|
||||
int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
||||
struct mt76_bus_ops *ops)
|
||||
{
|
||||
static struct mt76_bus_ops mt76u_ops = {
|
||||
.read_copy = mt76u_read_copy_ext,
|
||||
.wr_rp = mt76u_wr_rp,
|
||||
.rd_rp = mt76u_rd_rp,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int err;
|
||||
|
||||
mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr;
|
||||
mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr;
|
||||
mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw;
|
||||
mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy;
|
||||
|
||||
INIT_WORK(&usb->stat_work, mt76u_tx_status_data);
|
||||
|
||||
usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1);
|
||||
|
@ -1141,7 +1077,7 @@ int mt76u_init(struct mt76_dev *dev,
|
|||
return -ENOMEM;
|
||||
|
||||
mutex_init(&usb->usb_ctrl_mtx);
|
||||
dev->bus = &mt76u_ops;
|
||||
dev->bus = ops;
|
||||
dev->queue_ops = &usb_queue_ops;
|
||||
|
||||
dev_set_drvdata(&udev->dev, dev);
|
||||
|
@ -1167,6 +1103,23 @@ int mt76u_init(struct mt76_dev *dev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt76u_init);
|
||||
|
||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf)
|
||||
{
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt76u_rr,
|
||||
.wr = mt76u_wr,
|
||||
.rmw = mt76u_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt76u_copy,
|
||||
.wr_rp = mt76u_wr_rp,
|
||||
.rd_rp = mt76u_rd_rp,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
|
||||
return __mt76u_init(dev, intf, &bus_ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76u_init);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
|
||||
|
|
|
@ -334,6 +334,7 @@ static const struct usb_device_id rtl8192c_usb_ids[] = {
|
|||
{RTL_USB_DEVICE(0x04f2, 0xaff7, rtl92cu_hal_cfg)}, /*Xavi*/
|
||||
{RTL_USB_DEVICE(0x04f2, 0xaff9, rtl92cu_hal_cfg)}, /*Xavi*/
|
||||
{RTL_USB_DEVICE(0x04f2, 0xaffa, rtl92cu_hal_cfg)}, /*Xavi*/
|
||||
{RTL_USB_DEVICE(0x0846, 0x9042, rtl92cu_hal_cfg)}, /*On Netwrks N150MA*/
|
||||
|
||||
/****** 8188CUS Slim Combo ********/
|
||||
{RTL_USB_DEVICE(0x04f2, 0xaff8, rtl92cu_hal_cfg)}, /*Xavi*/
|
||||
|
|
|
@ -872,7 +872,7 @@ static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
|
|||
else
|
||||
falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
|
||||
|
||||
/*reset OFDM FA coutner*/
|
||||
/*reset OFDM FA counter*/
|
||||
rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
|
||||
rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
|
||||
/* reset CCK FA counter*/
|
||||
|
@ -1464,7 +1464,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
|
|||
const u8 *delta_swing_table_idx_tup_b;
|
||||
const u8 *delta_swing_table_idx_tdown_b;
|
||||
|
||||
/*2. Initilization ( 7 steps in total )*/
|
||||
/*2. Initialization ( 7 steps in total )*/
|
||||
rtl8812ae_get_delta_swing_table(hw,
|
||||
&delta_swing_table_idx_tup_a,
|
||||
&delta_swing_table_idx_tdown_a,
|
||||
|
@ -2502,7 +2502,7 @@ static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
|
|||
rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
|
||||
|
||||
/*===============================
|
||||
* list paramter for different platform
|
||||
* list parameter for different platform
|
||||
*===============================
|
||||
*/
|
||||
pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
|
||||
|
|
|
@ -1478,7 +1478,7 @@ static void _set_gnt_wl(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
|
|||
}
|
||||
}
|
||||
|
||||
rtw89_mac_cfg_gnt(rtwdev, &dm->gnt);
|
||||
rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
|
||||
}
|
||||
|
||||
#define BTC_TDMA_WLROLE_MAX 2
|
||||
|
@ -2233,7 +2233,7 @@ static void _set_gnt_bt(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
|
|||
}
|
||||
}
|
||||
|
||||
rtw89_mac_cfg_gnt(rtwdev, &dm->gnt);
|
||||
rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
|
||||
}
|
||||
|
||||
static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
|
||||
|
@ -2300,7 +2300,7 @@ static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
|
|||
|
||||
switch (type) {
|
||||
case BTC_ANT_WPOWERON:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, false);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, false);
|
||||
break;
|
||||
case BTC_ANT_WINIT:
|
||||
if (bt->enable.now) {
|
||||
|
@ -2310,21 +2310,21 @@ static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
|
|||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
|
||||
}
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
|
||||
break;
|
||||
case BTC_ANT_WONLY:
|
||||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
||||
break;
|
||||
case BTC_ANT_WOFF:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, false);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, false);
|
||||
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
||||
break;
|
||||
case BTC_ANT_W2G:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
if (rtwdev->dbcc_en) {
|
||||
for (i = 0; i < RTW89_PHY_MAX; i++) {
|
||||
b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
|
||||
|
@ -2352,32 +2352,32 @@ static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
|
|||
}
|
||||
break;
|
||||
case BTC_ANT_W5G:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
|
||||
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
||||
break;
|
||||
case BTC_ANT_W25G:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
|
||||
_set_bt_plut(rtwdev, BTC_PHY_ALL,
|
||||
BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
|
||||
break;
|
||||
case BTC_ANT_FREERUN:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
||||
break;
|
||||
case BTC_ANT_WRFK:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, true);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, true);
|
||||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
|
||||
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
|
||||
break;
|
||||
case BTC_ANT_BRFK:
|
||||
rtw89_mac_cfg_ctrl_path(rtwdev, false);
|
||||
rtw89_chip_cfg_ctrl_path(rtwdev, false);
|
||||
_set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
|
||||
_set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
|
||||
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
|
||||
|
@ -4623,12 +4623,12 @@ static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
|
|||
ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
|
||||
seq_printf(m, "(%s, desired:%d.%d.%d), ",
|
||||
(wl->ver_info.fw_coex >= chip->wlcx_desired ?
|
||||
"Match" : "Mis-Match"), ver_main, ver_sub, ver_hotfix);
|
||||
"Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
|
||||
|
||||
seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
|
||||
bt->ver_info.fw_coex,
|
||||
(bt->ver_info.fw_coex >= chip->btcx_desired ?
|
||||
"Match" : "Mis-Match"), chip->btcx_desired);
|
||||
"Match" : "Mismatch"), chip->btcx_desired);
|
||||
|
||||
if (bt->enable.now && bt->ver_info.fw == 0)
|
||||
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
|
||||
|
@ -5075,7 +5075,7 @@ static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
|
|||
seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
|
||||
(BTC_CX_FW_OFFLOAD ? "Y" : "N"),
|
||||
(dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
|
||||
"" : "(Mis-Match!!)"));
|
||||
"" : "(Mismatch!!)"));
|
||||
|
||||
if (dm->rf_trx_para.wl_tx_power == 0xff)
|
||||
seq_printf(m,
|
||||
|
|
|
@ -609,7 +609,7 @@ struct rtw89_channel_params {
|
|||
};
|
||||
|
||||
struct rtw89_channel_help_params {
|
||||
u16 tx_en;
|
||||
u32 tx_en;
|
||||
};
|
||||
|
||||
struct rtw89_port_reg {
|
||||
|
@ -2065,9 +2065,15 @@ struct rtw89_chip_ops {
|
|||
struct ieee80211_rx_status *status);
|
||||
void (*bb_ctrl_btc_preagc)(struct rtw89_dev *rtwdev, bool bt_en);
|
||||
void (*set_txpwr_ul_tb_offset)(struct rtw89_dev *rtwdev,
|
||||
s16 pw_ofst, enum rtw89_mac_idx mac_idx);
|
||||
s8 pw_ofst, enum rtw89_mac_idx mac_idx);
|
||||
int (*pwr_on_func)(struct rtw89_dev *rtwdev);
|
||||
int (*pwr_off_func)(struct rtw89_dev *rtwdev);
|
||||
int (*cfg_ctrl_path)(struct rtw89_dev *rtwdev, bool wl);
|
||||
int (*mac_cfg_gnt)(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
|
||||
int (*stop_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u32 *tx_en, enum rtw89_sch_tx_sel sel);
|
||||
int (*resume_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
|
||||
|
||||
void (*btc_set_rfe)(struct rtw89_dev *rtwdev);
|
||||
void (*btc_init_cfg)(struct rtw89_dev *rtwdev);
|
||||
|
@ -2229,6 +2235,8 @@ struct rtw89_phy_table {
|
|||
const struct rtw89_reg2_def *regs;
|
||||
u32 n_regs;
|
||||
enum rtw89_rf_path rf_path;
|
||||
void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg,
|
||||
enum rtw89_rf_path rf_path, void *data);
|
||||
};
|
||||
|
||||
struct rtw89_txpwr_table {
|
||||
|
@ -2332,6 +2340,8 @@ struct rtw89_chip_info {
|
|||
u32 c2h_ctrl_reg;
|
||||
const u32 *c2h_regs;
|
||||
const struct rtw89_page_regs *page_regs;
|
||||
const struct rtw89_reg_def *dcfo_comp;
|
||||
u8 dcfo_comp_sft;
|
||||
};
|
||||
|
||||
union rtw89_bus_info {
|
||||
|
@ -3463,6 +3473,39 @@ static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
|
|||
chip->ops->ctrl_btg(rtwdev, btg);
|
||||
}
|
||||
|
||||
static inline
|
||||
void rtw89_chip_mac_cfg_gnt(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mac_ax_coex_gnt *gnt_cfg)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->mac_cfg_gnt(rtwdev, gnt_cfg);
|
||||
}
|
||||
|
||||
static inline void rtw89_chip_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->cfg_ctrl_path(rtwdev, wl);
|
||||
}
|
||||
|
||||
static inline
|
||||
int rtw89_chip_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u32 *tx_en, enum rtw89_sch_tx_sel sel)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
return chip->ops->stop_sch_tx(rtwdev, mac_idx, tx_en, sel);
|
||||
}
|
||||
|
||||
static inline
|
||||
int rtw89_chip_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
return chip->ops->resume_sch_tx(rtwdev, mac_idx, tx_en);
|
||||
}
|
||||
|
||||
static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
|
|
@ -1964,7 +1964,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
|
|||
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
|
||||
struct rtw89_pktofld_info *info;
|
||||
struct sk_buff *new;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
u8 band;
|
||||
|
||||
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
|
||||
|
|
|
@ -1128,18 +1128,31 @@ static int cmac_func_en(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
|
|||
|
||||
static int dmac_func_en(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
u32 val32;
|
||||
|
||||
val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MAC_SEC_EN |
|
||||
B_AX_DISPATCHER_EN | B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
|
||||
B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN | B_AX_STA_SCH_EN |
|
||||
B_AX_TXPKT_CTRL_EN | B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN);
|
||||
if (chip_id == RTL8852C)
|
||||
val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
|
||||
B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
|
||||
B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
|
||||
B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
|
||||
B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
|
||||
B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
|
||||
B_AX_DMAC_CRPRT | B_AX_H_AXIDMA_EN);
|
||||
else
|
||||
val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
|
||||
B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
|
||||
B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
|
||||
B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
|
||||
B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
|
||||
B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
|
||||
B_AX_DMAC_CRPRT);
|
||||
rtw89_write32(rtwdev, R_AX_DMAC_FUNC_EN, val32);
|
||||
|
||||
val32 = (B_AX_MAC_SEC_CLK_EN | B_AX_DISPATCHER_CLK_EN |
|
||||
B_AX_DLE_CPUIO_CLK_EN | B_AX_PKT_IN_CLK_EN |
|
||||
B_AX_STA_SCH_CLK_EN | B_AX_TXPKT_CTRL_CLK_EN |
|
||||
B_AX_WD_RLS_CLK_EN);
|
||||
B_AX_WD_RLS_CLK_EN | B_AX_BBRPT_CLK_EN);
|
||||
rtw89_write32(rtwdev, R_AX_DMAC_CLK_EN, val32);
|
||||
|
||||
return 0;
|
||||
|
@ -1147,7 +1160,11 @@ static int dmac_func_en(struct rtw89_dev *rtwdev)
|
|||
|
||||
static int chip_func_en(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL0, B_AX_OCP_L1_MASK);
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
|
||||
if (chip_id == RTL8852A)
|
||||
rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL0,
|
||||
B_AX_OCP_L1_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1528,6 +1545,43 @@ error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int preload_init_set(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_qta_mode mode)
|
||||
{
|
||||
u32 reg, max_preld_size, min_rsvd_size;
|
||||
|
||||
max_preld_size = (mac_idx == RTW89_MAC_0 ?
|
||||
PRELD_B0_ENT_NUM : PRELD_B1_ENT_NUM) * PRELD_AMSDU_SIZE;
|
||||
reg = mac_idx == RTW89_MAC_0 ?
|
||||
R_AX_TXPKTCTL_B0_PRELD_CFG0 : R_AX_TXPKTCTL_B1_PRELD_CFG0;
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_USEMAXSZ_MASK, max_preld_size);
|
||||
rtw89_write32_set(rtwdev, reg, B_AX_B0_PRELD_FEN);
|
||||
|
||||
min_rsvd_size = PRELD_AMSDU_SIZE;
|
||||
reg = mac_idx == RTW89_MAC_0 ?
|
||||
R_AX_TXPKTCTL_B0_PRELD_CFG1 : R_AX_TXPKTCTL_B1_PRELD_CFG1;
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_NXT_TXENDWIN_MASK, PRELD_NEXT_WND);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_NXT_RSVMINSZ_MASK, min_rsvd_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_qta_poh(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
return rtwdev->hci.type == RTW89_HCI_TYPE_PCIE;
|
||||
}
|
||||
|
||||
static int preload_init(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_qta_mode mode)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || !is_qta_poh(rtwdev))
|
||||
return 0;
|
||||
|
||||
return preload_init_set(rtwdev, mac_idx, mode);
|
||||
}
|
||||
|
||||
static bool dle_is_txq_empty(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
u32 msk32;
|
||||
|
@ -1635,6 +1689,12 @@ static int dmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = preload_init(rtwdev, RTW89_MAC_0, rtwdev->mac.qta_mode);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "[ERR]preload init %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hfc_init(rtwdev, true, true, true);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "[ERR]HCI FC init %d\n", ret);
|
||||
|
@ -2186,8 +2246,26 @@ static int rtw89_set_hw_sch_tx_en(struct rtw89_dev *rtwdev, u8 mac_idx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rtw89_set_hw_sch_tx_en_v1(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u32 tx_en, u32 tx_en_mask)
|
||||
{
|
||||
u32 reg = rtw89_mac_reg_by_idx(R_AX_CTN_DRV_TXEN, mac_idx);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = rtw89_read32(rtwdev, reg);
|
||||
val = (val & ~tx_en_mask) | (tx_en & tx_en_mask);
|
||||
rtw89_write32(rtwdev, reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u16 *tx_en, enum rtw89_sch_tx_sel sel)
|
||||
u32 *tx_en, enum rtw89_sch_tx_sel sel)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -2196,7 +2274,8 @@ int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
|
|||
|
||||
switch (sel) {
|
||||
case RTW89_SCH_TX_SEL_ALL:
|
||||
ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, 0, 0xffff);
|
||||
ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, 0,
|
||||
B_AX_CTN_TXEN_ALL_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
@ -2213,7 +2292,8 @@ int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
|
|||
return ret;
|
||||
break;
|
||||
case RTW89_SCH_TX_SEL_MACID:
|
||||
ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, 0, 0xffff);
|
||||
ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, 0,
|
||||
B_AX_CTN_TXEN_ALL_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
@ -2225,11 +2305,52 @@ int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
|
|||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_stop_sch_tx);
|
||||
|
||||
int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u16 tx_en)
|
||||
int rtw89_mac_stop_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u32 *tx_en, enum rtw89_sch_tx_sel sel)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, tx_en, 0xffff);
|
||||
*tx_en = rtw89_read32(rtwdev,
|
||||
rtw89_mac_reg_by_idx(R_AX_CTN_DRV_TXEN, mac_idx));
|
||||
|
||||
switch (sel) {
|
||||
case RTW89_SCH_TX_SEL_ALL:
|
||||
ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx, 0,
|
||||
B_AX_CTN_TXEN_ALL_MASK_V1);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case RTW89_SCH_TX_SEL_HIQ:
|
||||
ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx,
|
||||
0, B_AX_CTN_TXEN_HGQ);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case RTW89_SCH_TX_SEL_MG0:
|
||||
ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx,
|
||||
0, B_AX_CTN_TXEN_MGQ);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case RTW89_SCH_TX_SEL_MACID:
|
||||
ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx, 0,
|
||||
B_AX_CTN_TXEN_ALL_MASK_V1);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_stop_sch_tx_v1);
|
||||
|
||||
int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, tx_en, B_AX_CTN_TXEN_ALL_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -2237,6 +2358,19 @@ int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u16 tx_en)
|
|||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_resume_sch_tx);
|
||||
|
||||
int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx, tx_en,
|
||||
B_AX_CTN_TXEN_ALL_MASK_V1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_resume_sch_tx_v1);
|
||||
|
||||
static u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len,
|
||||
bool wd)
|
||||
{
|
||||
|
@ -2399,9 +2533,9 @@ static int band1_enable(struct rtw89_dev *rtwdev)
|
|||
int ret, i;
|
||||
u32 sleep_bak[4] = {0};
|
||||
u32 pause_bak[4] = {0};
|
||||
u16 tx_en;
|
||||
u32 tx_en;
|
||||
|
||||
ret = rtw89_mac_stop_sch_tx(rtwdev, 0, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
ret = rtw89_chip_stop_sch_tx(rtwdev, 0, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "[ERR]stop sch tx %d\n", ret);
|
||||
return ret;
|
||||
|
@ -2431,7 +2565,7 @@ static int band1_enable(struct rtw89_dev *rtwdev)
|
|||
rtw89_write32(rtwdev, R_AX_SS_MACID_PAUSE_0 + i * 4, pause_bak[i]);
|
||||
}
|
||||
|
||||
ret = rtw89_mac_resume_sch_tx(rtwdev, 0, tx_en);
|
||||
ret = rtw89_chip_resume_sch_tx(rtwdev, 0, tx_en);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "[ERR]CMAC1 resume sch tx %d\n", ret);
|
||||
return ret;
|
||||
|
@ -2625,7 +2759,11 @@ static void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev)
|
|||
clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
|
||||
|
||||
rtw89_write32_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_WCPU_EN);
|
||||
rtw89_write32_clr(rtwdev, R_AX_WCPU_FW_CTRL, B_AX_WCPU_FWDL_EN |
|
||||
B_AX_H2C_PATH_RDY | B_AX_FWDL_PATH_RDY);
|
||||
rtw89_write32_clr(rtwdev, R_AX_SYS_CLK_CTRL, B_AX_CPU_CLK_EN);
|
||||
rtw89_write32_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
|
||||
rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
|
||||
}
|
||||
|
||||
static int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason,
|
||||
|
@ -3557,29 +3695,32 @@ EXPORT_SYMBOL(rtw89_mac_coex_init);
|
|||
int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mac_ax_coex_gnt *gnt_cfg)
|
||||
{
|
||||
u32 val, ret;
|
||||
u32 val = 0, ret;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_bt)
|
||||
val |= B_AX_GNT_BT_RFC_S0_SW_VAL | B_AX_GNT_BT_BB_S0_SW_VAL;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_bt_sw_en)
|
||||
val |= B_AX_GNT_BT_RFC_S0_SW_CTRL | B_AX_GNT_BT_BB_S0_SW_CTRL;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_wl)
|
||||
val |= B_AX_GNT_WL_RFC_S0_SW_VAL | B_AX_GNT_WL_BB_S0_SW_VAL;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_wl_sw_en)
|
||||
val |= B_AX_GNT_WL_RFC_S0_SW_CTRL | B_AX_GNT_WL_BB_S0_SW_CTRL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_bt)
|
||||
val |= B_AX_GNT_BT_RFC_S1_SW_VAL | B_AX_GNT_BT_BB_S1_SW_VAL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_bt_sw_en)
|
||||
val |= B_AX_GNT_BT_RFC_S1_SW_CTRL | B_AX_GNT_BT_BB_S1_SW_CTRL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_wl)
|
||||
val |= B_AX_GNT_WL_RFC_S1_SW_VAL | B_AX_GNT_WL_BB_S1_SW_VAL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_wl_sw_en)
|
||||
val |= B_AX_GNT_WL_RFC_S1_SW_CTRL | B_AX_GNT_WL_BB_S1_SW_CTRL;
|
||||
|
||||
ret = rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "Read LTE fail!\n");
|
||||
return ret;
|
||||
}
|
||||
val = (gnt_cfg->band[0].gnt_bt ?
|
||||
B_AX_GNT_BT_RFC_S0_SW_VAL | B_AX_GNT_BT_BB_S0_SW_VAL : 0) |
|
||||
(gnt_cfg->band[0].gnt_bt_sw_en ?
|
||||
B_AX_GNT_BT_RFC_S0_SW_CTRL | B_AX_GNT_BT_BB_S0_SW_CTRL : 0) |
|
||||
(gnt_cfg->band[0].gnt_wl ?
|
||||
B_AX_GNT_WL_RFC_S0_SW_VAL | B_AX_GNT_WL_BB_S0_SW_VAL : 0) |
|
||||
(gnt_cfg->band[0].gnt_wl_sw_en ?
|
||||
B_AX_GNT_WL_RFC_S0_SW_CTRL | B_AX_GNT_WL_BB_S0_SW_CTRL : 0) |
|
||||
(gnt_cfg->band[1].gnt_bt ?
|
||||
B_AX_GNT_BT_RFC_S1_SW_VAL | B_AX_GNT_BT_BB_S1_SW_VAL : 0) |
|
||||
(gnt_cfg->band[1].gnt_bt_sw_en ?
|
||||
B_AX_GNT_BT_RFC_S1_SW_CTRL | B_AX_GNT_BT_BB_S1_SW_CTRL : 0) |
|
||||
(gnt_cfg->band[1].gnt_wl ?
|
||||
B_AX_GNT_WL_RFC_S1_SW_VAL | B_AX_GNT_WL_BB_S1_SW_VAL : 0) |
|
||||
(gnt_cfg->band[1].gnt_wl_sw_en ?
|
||||
B_AX_GNT_WL_RFC_S1_SW_CTRL | B_AX_GNT_WL_BB_S1_SW_CTRL : 0);
|
||||
ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_1, val);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "Write LTE fail!\n");
|
||||
|
@ -3588,6 +3729,54 @@ int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_cfg_gnt);
|
||||
|
||||
int rtw89_mac_cfg_gnt_v1(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mac_ax_coex_gnt *gnt_cfg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_bt)
|
||||
val |= B_AX_GNT_BT_RFC_S0_VAL | B_AX_GNT_BT_RX_VAL |
|
||||
B_AX_GNT_BT_TX_VAL;
|
||||
else
|
||||
val |= B_AX_WL_ACT_VAL;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_bt_sw_en)
|
||||
val |= B_AX_GNT_BT_RFC_S0_SWCTRL | B_AX_GNT_BT_RX_SWCTRL |
|
||||
B_AX_GNT_BT_TX_SWCTRL | B_AX_WL_ACT_SWCTRL;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_wl)
|
||||
val |= B_AX_GNT_WL_RFC_S0_VAL | B_AX_GNT_WL_RX_VAL |
|
||||
B_AX_GNT_WL_TX_VAL | B_AX_GNT_WL_BB_VAL;
|
||||
|
||||
if (gnt_cfg->band[0].gnt_wl_sw_en)
|
||||
val |= B_AX_GNT_WL_RFC_S0_SWCTRL | B_AX_GNT_WL_RX_SWCTRL |
|
||||
B_AX_GNT_WL_TX_SWCTRL | B_AX_GNT_WL_BB_SWCTRL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_bt)
|
||||
val |= B_AX_GNT_BT_RFC_S1_VAL | B_AX_GNT_BT_RX_VAL |
|
||||
B_AX_GNT_BT_TX_VAL;
|
||||
else
|
||||
val |= B_AX_WL_ACT_VAL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_bt_sw_en)
|
||||
val |= B_AX_GNT_BT_RFC_S1_SWCTRL | B_AX_GNT_BT_RX_SWCTRL |
|
||||
B_AX_GNT_BT_TX_SWCTRL | B_AX_WL_ACT_SWCTRL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_wl)
|
||||
val |= B_AX_GNT_WL_RFC_S1_VAL | B_AX_GNT_WL_RX_VAL |
|
||||
B_AX_GNT_WL_TX_VAL | B_AX_GNT_WL_BB_VAL;
|
||||
|
||||
if (gnt_cfg->band[1].gnt_wl_sw_en)
|
||||
val |= B_AX_GNT_WL_RFC_S1_SWCTRL | B_AX_GNT_WL_RX_SWCTRL |
|
||||
B_AX_GNT_WL_TX_SWCTRL | B_AX_GNT_WL_BB_SWCTRL;
|
||||
|
||||
rtw89_write32(rtwdev, R_AX_GNT_SW_CTRL, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_cfg_gnt_v1);
|
||||
|
||||
int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt)
|
||||
{
|
||||
|
@ -3647,6 +3836,28 @@ int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_cfg_ctrl_path);
|
||||
|
||||
int rtw89_mac_cfg_ctrl_path_v1(struct rtw89_dev *rtwdev, bool wl)
|
||||
{
|
||||
struct rtw89_btc *btc = &rtwdev->btc;
|
||||
struct rtw89_btc_dm *dm = &btc->dm;
|
||||
struct rtw89_mac_ax_gnt *g = dm->gnt.band;
|
||||
int i;
|
||||
|
||||
if (wl)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < RTW89_PHY_MAX; i++) {
|
||||
g[i].gnt_bt_sw_en = 1;
|
||||
g[i].gnt_bt = 1;
|
||||
g[i].gnt_wl_sw_en = 1;
|
||||
g[i].gnt_wl = 0;
|
||||
}
|
||||
|
||||
return rtw89_mac_cfg_gnt_v1(rtwdev, &dm->gnt);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_mac_cfg_ctrl_path_v1);
|
||||
|
||||
bool rtw89_mac_get_ctrl_path(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
|
|
|
@ -791,20 +791,26 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
|
|||
u32 len, u8 class, u8 func);
|
||||
int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev);
|
||||
int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u16 *tx_en, enum rtw89_sch_tx_sel sel);
|
||||
int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u16 tx_en);
|
||||
u32 *tx_en, enum rtw89_sch_tx_sel sel);
|
||||
int rtw89_mac_stop_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx,
|
||||
u32 *tx_en, enum rtw89_sch_tx_sel sel);
|
||||
int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
|
||||
int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
|
||||
int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_ids, bool enable);
|
||||
void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx);
|
||||
void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop);
|
||||
int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex);
|
||||
int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
|
||||
int rtw89_mac_cfg_gnt_v1(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
|
||||
int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
|
||||
u16 rtw89_mac_get_plt_cnt(struct rtw89_dev *rtwdev, u8 band);
|
||||
void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val);
|
||||
u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev);
|
||||
bool rtw89_mac_get_ctrl_path(struct rtw89_dev *rtwdev);
|
||||
int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl);
|
||||
int rtw89_mac_cfg_ctrl_path_v1(struct rtw89_dev *rtwdev, bool wl);
|
||||
bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx,
|
||||
u32 reg_base, u32 *cr);
|
||||
|
@ -884,7 +890,9 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
|
|||
|
||||
enum rtw89_mac_xtal_si_offset {
|
||||
XTAL_SI_XTAL_SC_XI = 0x04,
|
||||
#define XTAL_SC_XI_MASK GENMASK(7, 0)
|
||||
XTAL_SI_XTAL_SC_XO = 0x05,
|
||||
#define XTAL_SC_XO_MASK GENMASK(7, 0)
|
||||
XTAL_SI_PWR_CUT = 0x10,
|
||||
#define XTAL_SI_SMALL_PWR_CUT BIT(0)
|
||||
#define XTAL_SI_BIG_PWR_CUT BIT(1)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
#include "mac.h"
|
||||
#include "phy.h"
|
||||
#include "ps.h"
|
||||
#include "reg.h"
|
||||
|
@ -603,6 +604,12 @@ u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_get_txsc);
|
||||
|
||||
static bool rtw89_phy_check_swsi_busy(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
return !!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_W_BUSY_V1) ||
|
||||
!!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_R_BUSY_V1);
|
||||
}
|
||||
|
||||
u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask)
|
||||
{
|
||||
|
@ -625,6 +632,56 @@ u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
|||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_read_rf);
|
||||
|
||||
static u32 rtw89_phy_read_rf_a(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_rf_path rf_path, u32 addr, u32 mask)
|
||||
{
|
||||
bool busy;
|
||||
bool done;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw89_phy_check_swsi_busy, busy, !busy,
|
||||
1, 30, false, rtwdev);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "read rf busy swsi\n");
|
||||
return INV_RF_DATA;
|
||||
}
|
||||
|
||||
mask &= RFREG_MASK;
|
||||
|
||||
val = FIELD_PREP(B_SWSI_READ_ADDR_PATH_V1, rf_path) |
|
||||
FIELD_PREP(B_SWSI_READ_ADDR_ADDR_V1, addr);
|
||||
rtw89_phy_write32_mask(rtwdev, R_SWSI_READ_ADDR_V1, B_SWSI_READ_ADDR_V1, val);
|
||||
udelay(2);
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done, 1,
|
||||
30, false, rtwdev, R_SWSI_V1,
|
||||
B_SWSI_R_DATA_DONE_V1);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "read swsi busy\n");
|
||||
return INV_RF_DATA;
|
||||
}
|
||||
|
||||
return rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, mask);
|
||||
}
|
||||
|
||||
u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask)
|
||||
{
|
||||
bool ad_sel = FIELD_GET(RTW89_RF_ADDR_ADSEL_MASK, addr);
|
||||
|
||||
if (rf_path >= rtwdev->chip->rf_path_num) {
|
||||
rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
|
||||
return INV_RF_DATA;
|
||||
}
|
||||
|
||||
if (ad_sel)
|
||||
return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
|
||||
else
|
||||
return rtw89_phy_read_rf_a(rtwdev, rf_path, addr, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_read_rf_v1);
|
||||
|
||||
bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
|
@ -650,6 +707,60 @@ bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
|||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_write_rf);
|
||||
|
||||
static bool rtw89_phy_write_rf_a(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_rf_path rf_path, u32 addr, u32 mask,
|
||||
u32 data)
|
||||
{
|
||||
u8 bit_shift;
|
||||
u32 val;
|
||||
bool busy, b_msk_en = false;
|
||||
int ret;
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw89_phy_check_swsi_busy, busy, !busy,
|
||||
1, 30, false, rtwdev);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "write rf busy swsi\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
data &= RFREG_MASK;
|
||||
mask &= RFREG_MASK;
|
||||
|
||||
if (mask != RFREG_MASK) {
|
||||
b_msk_en = true;
|
||||
rtw89_phy_write32_mask(rtwdev, R_SWSI_BIT_MASK_V1, RFREG_MASK,
|
||||
mask);
|
||||
bit_shift = __ffs(mask);
|
||||
data = (data << bit_shift) & RFREG_MASK;
|
||||
}
|
||||
|
||||
val = FIELD_PREP(B_SWSI_DATA_BIT_MASK_EN_V1, b_msk_en) |
|
||||
FIELD_PREP(B_SWSI_DATA_PATH_V1, rf_path) |
|
||||
FIELD_PREP(B_SWSI_DATA_ADDR_V1, addr) |
|
||||
FIELD_PREP(B_SWSI_DATA_VAL_V1, data);
|
||||
|
||||
rtw89_phy_write32_mask(rtwdev, R_SWSI_DATA_V1, MASKDWORD, val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
bool ad_sel = FIELD_GET(RTW89_RF_ADDR_ADSEL_MASK, addr);
|
||||
|
||||
if (rf_path >= rtwdev->chip->rf_path_num) {
|
||||
rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ad_sel)
|
||||
return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
|
||||
else
|
||||
return rtw89_phy_write_rf_a(rtwdev, rf_path, addr, mask, data);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_write_rf_v1);
|
||||
|
||||
static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
|
@ -751,6 +862,21 @@ static void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
}
|
||||
|
||||
void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_reg2_def *reg,
|
||||
enum rtw89_rf_path rf_path,
|
||||
void *extra_data)
|
||||
{
|
||||
rtw89_write_rf(rtwdev, rf_path, reg->addr, RFREG_MASK, reg->data);
|
||||
|
||||
if (reg->addr < 0x100)
|
||||
return;
|
||||
|
||||
rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
|
||||
(struct rtw89_fw_h2c_rf_reg_info *)extra_data);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_config_rf_reg_v1);
|
||||
|
||||
static int rtw89_phy_sel_headline(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_phy_table *table,
|
||||
u32 *headline_size, u32 *headline_idx,
|
||||
|
@ -922,6 +1048,8 @@ static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev)
|
|||
|
||||
void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg,
|
||||
enum rtw89_rf_path rf_path, void *data);
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw89_phy_table *rf_table;
|
||||
struct rtw89_fw_h2c_rf_reg_info *rf_reg_info;
|
||||
|
@ -932,13 +1060,13 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev)
|
|||
return;
|
||||
|
||||
for (path = RF_PATH_A; path < chip->rf_path_num; path++) {
|
||||
rf_reg_info->rf_path = path;
|
||||
rf_table = chip->rf_table[path];
|
||||
rtw89_phy_init_reg(rtwdev, rf_table, rtw89_phy_config_rf_reg,
|
||||
(void *)rf_reg_info);
|
||||
rf_reg_info->rf_path = rf_table->rf_path;
|
||||
config = rf_table->config ? rf_table->config : rtw89_phy_config_rf_reg;
|
||||
rtw89_phy_init_reg(rtwdev, rf_table, config, (void *)rf_reg_info);
|
||||
if (rtw89_phy_config_rf_reg_fw(rtwdev, rf_reg_info))
|
||||
rtw89_warn(rtwdev, "rf path %d reg h2c config failed\n",
|
||||
path);
|
||||
rf_reg_info->rf_path);
|
||||
}
|
||||
kfree(rf_reg_info);
|
||||
}
|
||||
|
@ -1667,15 +1795,25 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
|
|||
u8 crystal_cap, bool force)
|
||||
{
|
||||
struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
u8 sc_xi_val, sc_xo_val;
|
||||
|
||||
if (!force && cfo->crystal_cap == crystal_cap)
|
||||
return;
|
||||
crystal_cap = clamp_t(u8, crystal_cap, 0, 127);
|
||||
rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
|
||||
rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
|
||||
sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true);
|
||||
sc_xi_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, false);
|
||||
if (chip->chip_id == RTL8852A) {
|
||||
rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
|
||||
rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
|
||||
sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true);
|
||||
sc_xi_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, false);
|
||||
} else {
|
||||
rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XO,
|
||||
crystal_cap, XTAL_SC_XO_MASK);
|
||||
rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XI,
|
||||
crystal_cap, XTAL_SC_XI_MASK);
|
||||
rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XO, &sc_xo_val);
|
||||
rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XI, &sc_xi_val);
|
||||
}
|
||||
cfo->crystal_cap = sc_xi_val;
|
||||
cfo->x_cap_ofst = (s8)((int)cfo->crystal_cap - cfo->def_x_cap);
|
||||
|
||||
|
@ -1705,9 +1843,11 @@ static void rtw89_phy_cfo_reset(struct rtw89_dev *rtwdev)
|
|||
|
||||
static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
|
||||
{
|
||||
const struct rtw89_reg_def *dcfo_comp = rtwdev->chip->dcfo_comp;
|
||||
bool is_linked = rtwdev->total_sta_assoc > 0;
|
||||
s32 cfo_avg_312;
|
||||
s32 dcfo_comp;
|
||||
s32 dcfo_comp_val;
|
||||
u8 dcfo_comp_sft = rtwdev->chip->dcfo_comp_sft;
|
||||
int sign;
|
||||
|
||||
if (!is_linked) {
|
||||
|
@ -1718,13 +1858,13 @@ static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
|
|||
rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: curr_cfo=%d\n", curr_cfo);
|
||||
if (curr_cfo == 0)
|
||||
return;
|
||||
dcfo_comp = rtw89_phy_read32_mask(rtwdev, R_DCFO, B_DCFO);
|
||||
dcfo_comp_val = rtw89_phy_read32_mask(rtwdev, R_DCFO, B_DCFO);
|
||||
sign = curr_cfo > 0 ? 1 : -1;
|
||||
cfo_avg_312 = (curr_cfo << 3) / 5 + sign * dcfo_comp;
|
||||
cfo_avg_312 = (curr_cfo << dcfo_comp_sft) / 5 + sign * dcfo_comp_val;
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: avg_cfo=%d\n", cfo_avg_312);
|
||||
if (rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv == CHIP_CBV)
|
||||
cfo_avg_312 = -cfo_avg_312;
|
||||
rtw89_phy_set_phy_regs(rtwdev, R_DCFO_COMP_S0, B_DCFO_COMP_S0_MSK,
|
||||
rtw89_phy_set_phy_regs(rtwdev, dcfo_comp->addr, dcfo_comp->mask,
|
||||
cfo_avg_312);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "core.h"
|
||||
|
||||
#define RTW89_PHY_ADDR_OFFSET 0x10000
|
||||
#define RTW89_RF_ADDR_ADSEL_MASK BIT(16)
|
||||
|
||||
#define get_phy_headline(addr) FIELD_GET(GENMASK(31, 28), addr)
|
||||
#define PHY_HEADLINE_VALID 0xf
|
||||
|
@ -395,10 +396,18 @@ u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
|
|||
enum rtw89_bandwidth dbw);
|
||||
u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask);
|
||||
u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask);
|
||||
bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data);
|
||||
bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data);
|
||||
void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
|
||||
void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev);
|
||||
void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_reg2_def *reg,
|
||||
enum rtw89_rf_path rf_path,
|
||||
void *extra_data);
|
||||
void rtw89_phy_dm_init(struct rtw89_dev *rtwdev);
|
||||
void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
|
||||
u32 data, enum rtw89_phy_idx phy_idx);
|
||||
|
|
|
@ -312,6 +312,7 @@
|
|||
#define R_AX_BOOT_DBG 0x83F0
|
||||
|
||||
#define R_AX_DMAC_FUNC_EN 0x8400
|
||||
#define B_AX_DMAC_CRPRT BIT(31)
|
||||
#define B_AX_MAC_FUNC_EN BIT(30)
|
||||
#define B_AX_DMAC_FUNC_EN BIT(29)
|
||||
#define B_AX_MPDU_PROC_EN BIT(28)
|
||||
|
@ -339,6 +340,7 @@
|
|||
#define B_AX_PKT_IN_CLK_EN BIT(20)
|
||||
#define B_AX_DLE_CPUIO_CLK_EN BIT(19)
|
||||
#define B_AX_DISPATCHER_CLK_EN BIT(18)
|
||||
#define B_AX_BBRPT_CLK_EN BIT(17)
|
||||
#define B_AX_MAC_SEC_CLK_EN BIT(16)
|
||||
|
||||
#define PCI_LTR_IDLE_TIMER_1US 0
|
||||
|
@ -740,6 +742,30 @@
|
|||
#define R_AX_DBG_FUN_INTF_DATA 0x9F34
|
||||
#define B_AX_DFI_DATA_MASK GENMASK(31, 0)
|
||||
|
||||
#define R_AX_TXPKTCTL_B0_PRELD_CFG0 0x9F48
|
||||
#define B_AX_B0_PRELD_FEN BIT(31)
|
||||
#define B_AX_B0_PRELD_USEMAXSZ_MASK GENMASK(25, 16)
|
||||
#define PRELD_B0_ENT_NUM 10
|
||||
#define PRELD_AMSDU_SIZE 52
|
||||
#define B_AX_B0_PRELD_CAM_G1ENTNUM_MASK GENMASK(12, 8)
|
||||
#define B_AX_B0_PRELD_CAM_G0ENTNUM_MASK GENMASK(4, 0)
|
||||
|
||||
#define R_AX_TXPKTCTL_B0_PRELD_CFG1 0x9F4C
|
||||
#define B_AX_B0_PRELD_NXT_TXENDWIN_MASK GENMASK(11, 8)
|
||||
#define PRELD_NEXT_WND 1
|
||||
#define B_AX_B0_PRELD_NXT_RSVMINSZ_MASK GENMASK(7, 0)
|
||||
|
||||
#define R_AX_TXPKTCTL_B1_PRELD_CFG0 0x9F88
|
||||
#define B_AX_B1_PRELD_FEN BIT(31)
|
||||
#define B_AX_B1_PRELD_USEMAXSZ_MASK GENMASK(25, 16)
|
||||
#define PRELD_B1_ENT_NUM 4
|
||||
#define B_AX_B1_PRELD_CAM_G1ENTNUM_MASK GENMASK(12, 8)
|
||||
#define B_AX_B1_PRELD_CAM_G0ENTNUM_MASK GENMASK(4, 0)
|
||||
|
||||
#define R_AX_TXPKTCTL_B1_PRELD_CFG1 0x9F8C
|
||||
#define B_AX_B1_PRELD_NXT_TXENDWIN_MASK GENMASK(11, 8)
|
||||
#define B_AX_B1_PRELD_NXT_RSVMINSZ_MASK GENMASK(7, 0)
|
||||
|
||||
#define R_AX_AFE_CTRL1 0x0024
|
||||
|
||||
#define B_AX_R_SYM_WLCMAC1_P4_PC_EN BIT(4)
|
||||
|
@ -867,6 +893,7 @@
|
|||
#define B_AX_CTN_TXEN_VI_0 BIT(2)
|
||||
#define B_AX_CTN_TXEN_BK_0 BIT(1)
|
||||
#define B_AX_CTN_TXEN_BE_0 BIT(0)
|
||||
#define B_AX_CTN_TXEN_ALL_MASK GENMASK(15, 0)
|
||||
|
||||
#define R_AX_MUEDCA_BE_PARAM_0 0xC350
|
||||
#define R_AX_MUEDCA_BE_PARAM_0_C1 0xE350
|
||||
|
@ -913,6 +940,12 @@
|
|||
#define B_AX_CTN_CHK_CCA_S20 BIT(1)
|
||||
#define B_AX_CTN_CHK_CCA_P20 BIT(0)
|
||||
|
||||
#define R_AX_CTN_DRV_TXEN 0xC398
|
||||
#define R_AX_CTN_DRV_TXEN_C1 0xE398
|
||||
#define B_AX_CTN_TXEN_TWT_3 BIT(17)
|
||||
#define B_AX_CTN_TXEN_TWT_2 BIT(16)
|
||||
#define B_AX_CTN_TXEN_ALL_MASK_V1 GENMASK(17, 0)
|
||||
|
||||
#define R_AX_SCHEDULE_ERR_IMR 0xC3E8
|
||||
#define R_AX_SCHEDULE_ERR_IMR_C1 0xE3E8
|
||||
#define B_AX_SORT_NON_IDLE_ERR_INT_EN BIT(1)
|
||||
|
@ -1525,8 +1558,10 @@
|
|||
#define B_AX_PWR_UL_TB_CTRL_EN BIT(31)
|
||||
#define R_AX_PWR_UL_TB_1T 0xD28C
|
||||
#define B_AX_PWR_UL_TB_1T_MASK GENMASK(4, 0)
|
||||
#define B_AX_PWR_UL_TB_1T_V1_MASK GENMASK(7, 0)
|
||||
#define R_AX_PWR_UL_TB_2T 0xD290
|
||||
#define B_AX_PWR_UL_TB_2T_MASK GENMASK(4, 0)
|
||||
#define B_AX_PWR_UL_TB_2T_V1_MASK GENMASK(7, 0)
|
||||
#define R_AX_PWR_BY_RATE_TABLE0 0xD2C0
|
||||
#define R_AX_PWR_BY_RATE_TABLE10 0xD2E8
|
||||
#define R_AX_PWR_BY_RATE R_AX_PWR_BY_RATE_TABLE0
|
||||
|
@ -1592,6 +1627,31 @@
|
|||
#define B_AX_STATIS_BT_LO_TX_1_MASK GENMASK(15, 0)
|
||||
#define B_AX_STATIS_BT_LO_RX_1_MASK GENMASK(31, 16)
|
||||
|
||||
#define R_AX_GNT_SW_CTRL 0xDA48
|
||||
#define R_AX_GNT_SW_CTRL_C1 0xFA48
|
||||
#define B_AX_WL_ACT2_VAL BIT(21)
|
||||
#define B_AX_WL_ACT2_SWCTRL BIT(20)
|
||||
#define B_AX_WL_ACT_VAL BIT(19)
|
||||
#define B_AX_WL_ACT_SWCTRL BIT(18)
|
||||
#define B_AX_GNT_BT_RX_VAL BIT(17)
|
||||
#define B_AX_GNT_BT_RX_SWCTRL BIT(16)
|
||||
#define B_AX_GNT_BT_TX_VAL BIT(15)
|
||||
#define B_AX_GNT_BT_TX_SWCTRL BIT(14)
|
||||
#define B_AX_GNT_WL_RX_VAL BIT(13)
|
||||
#define B_AX_GNT_WL_RX_SWCTRL BIT(12)
|
||||
#define B_AX_GNT_WL_TX_VAL BIT(11)
|
||||
#define B_AX_GNT_WL_TX_SWCTRL BIT(10)
|
||||
#define B_AX_GNT_BT_RFC_S1_VAL BIT(9)
|
||||
#define B_AX_GNT_BT_RFC_S1_SWCTRL BIT(8)
|
||||
#define B_AX_GNT_WL_RFC_S1_VAL BIT(7)
|
||||
#define B_AX_GNT_WL_RFC_S1_SWCTRL BIT(6)
|
||||
#define B_AX_GNT_BT_RFC_S0_VAL BIT(5)
|
||||
#define B_AX_GNT_BT_RFC_S0_SWCTRL BIT(4)
|
||||
#define B_AX_GNT_WL_RFC_S0_VAL BIT(3)
|
||||
#define B_AX_GNT_WL_RFC_S0_SWCTRL BIT(2)
|
||||
#define B_AX_GNT_WL_BB_VAL BIT(1)
|
||||
#define B_AX_GNT_WL_BB_SWCTRL BIT(0)
|
||||
|
||||
#define R_AX_TDMA_MODE 0xDA4C
|
||||
#define R_AX_TDMA_MODE_C1 0xFA4C
|
||||
#define B_AX_R_BT_CMD_RPT_MASK GENMASK(31, 16)
|
||||
|
@ -1803,6 +1863,17 @@
|
|||
#define B_ANAPAR_FLTRST BIT(22)
|
||||
#define B_ANAPAR_CRXBB GENMASK(18, 16)
|
||||
#define B_ANAPAR_14 GENMASK(15, 0)
|
||||
#define R_SWSI_DATA_V1 0x0370
|
||||
#define B_SWSI_DATA_VAL_V1 GENMASK(19, 0)
|
||||
#define B_SWSI_DATA_ADDR_V1 GENMASK(27, 20)
|
||||
#define B_SWSI_DATA_PATH_V1 GENMASK(30, 28)
|
||||
#define B_SWSI_DATA_BIT_MASK_EN_V1 BIT(31)
|
||||
#define R_SWSI_BIT_MASK_V1 0x0374
|
||||
#define B_SWSI_BIT_MASK_V1 GENMASK(19, 0)
|
||||
#define R_SWSI_READ_ADDR_V1 0x0378
|
||||
#define B_SWSI_READ_ADDR_ADDR_V1 GENMASK(7, 0)
|
||||
#define B_SWSI_READ_ADDR_PATH_V1 GENMASK(10, 8)
|
||||
#define B_SWSI_READ_ADDR_V1 GENMASK(10, 0)
|
||||
#define R_UPD_CLK_ADC 0x0700
|
||||
#define B_UPD_CLK_ADC_ON BIT(24)
|
||||
#define B_UPD_CLK_ADC_VAL GENMASK(26, 25)
|
||||
|
@ -1910,6 +1981,10 @@
|
|||
#define R_CFO_COMP_SEG0_H 0x1388
|
||||
#define R_CFO_COMP_SEG0_CTRL 0x138C
|
||||
#define R_DBG32_D 0x1730
|
||||
#define R_SWSI_V1 0x174C
|
||||
#define B_SWSI_W_BUSY_V1 BIT(24)
|
||||
#define B_SWSI_R_BUSY_V1 BIT(25)
|
||||
#define B_SWSI_R_DATA_DONE_V1 BIT(26)
|
||||
#define R_TX_COUNTER 0x1A40
|
||||
#define R_IFS_CLM_TX_CNT 0x1ACC
|
||||
#define B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK GENMASK(31, 16)
|
||||
|
@ -2093,6 +2168,8 @@
|
|||
#define R_CHBW_MOD 0x4978
|
||||
#define B_CHBW_MOD_PRICH GENMASK(11, 8)
|
||||
#define B_CHBW_MOD_SBW GENMASK(13, 12)
|
||||
#define R_DCFO_COMP_S0_V1 0x4A40
|
||||
#define B_DCFO_COMP_S0_V1_MSK GENMASK(13, 0)
|
||||
#define R_BMODE_PDTH_V1 0x4B64
|
||||
#define B_BMODE_PDTH_LOWER_BOUND_MSK_V1 GENMASK(31, 24)
|
||||
#define R_BMODE_PDTH_EN_V1 0x4B74
|
||||
|
|
|
@ -402,6 +402,10 @@ static const struct rtw89_page_regs rtw8852a_page_regs = {
|
|||
.wp_page_info1 = R_AX_WP_PAGE_INFO1,
|
||||
};
|
||||
|
||||
static const struct rtw89_reg_def rtw8852a_dcfo_comp = {
|
||||
R_DCFO_COMP_S0, B_DCFO_COMP_S0_MSK
|
||||
};
|
||||
|
||||
static void rtw8852ae_efuse_parsing(struct rtw89_efuse *efuse,
|
||||
struct rtw8852a_efuse *map)
|
||||
{
|
||||
|
@ -1163,7 +1167,7 @@ static void rtw8852a_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
|
|||
u8 phy_idx = RTW89_PHY_0;
|
||||
|
||||
if (enter) {
|
||||
rtw89_mac_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
|
||||
rtw8852a_dfs_en(rtwdev, false);
|
||||
rtw8852a_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
|
||||
|
@ -1176,7 +1180,7 @@ static void rtw8852a_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
|
|||
rtw8852a_dfs_en(rtwdev, true);
|
||||
rtw8852a_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
|
||||
rtw8852a_bb_reset_en(rtwdev, phy_idx, true);
|
||||
rtw89_mac_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1271,10 +1275,10 @@ static u32 rtw8852a_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
|
|||
|
||||
static
|
||||
void rtw8852a_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
|
||||
s16 pw_ofst, enum rtw89_mac_idx mac_idx)
|
||||
s8 pw_ofst, enum rtw89_mac_idx mac_idx)
|
||||
{
|
||||
s32 val_1t = 0;
|
||||
s32 val_2t = 0;
|
||||
s8 val_1t = 0;
|
||||
s8 val_2t = 0;
|
||||
u32 reg;
|
||||
|
||||
if (pw_ofst < -16 || pw_ofst > 15) {
|
||||
|
@ -1284,7 +1288,7 @@ void rtw8852a_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx);
|
||||
rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN);
|
||||
val_1t = (s32)pw_ofst;
|
||||
val_1t = pw_ofst;
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, val_1t);
|
||||
val_2t = max(val_1t - 3, -16);
|
||||
|
@ -2015,6 +2019,10 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
|
|||
.set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset,
|
||||
.pwr_on_func = NULL,
|
||||
.pwr_off_func = NULL,
|
||||
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
|
||||
.mac_cfg_gnt = rtw89_mac_cfg_gnt,
|
||||
.stop_sch_tx = rtw89_mac_stop_sch_tx,
|
||||
.resume_sch_tx = rtw89_mac_resume_sch_tx,
|
||||
|
||||
.btc_set_rfe = rtw8852a_btc_set_rfe,
|
||||
.btc_init_cfg = rtw8852a_btc_init_cfg,
|
||||
|
@ -2091,6 +2099,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
|
|||
.c2h_ctrl_reg = R_AX_C2HREG_CTRL,
|
||||
.c2h_regs = rtw8852a_c2h_regs,
|
||||
.page_regs = &rtw8852a_page_regs,
|
||||
.dcfo_comp = &rtw8852a_dcfo_comp,
|
||||
.dcfo_comp_sft = 3,
|
||||
};
|
||||
EXPORT_SYMBOL(rtw8852a_chip_info);
|
||||
|
||||
|
|
|
@ -3526,7 +3526,7 @@ static void _tssi_pre_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
|||
const struct rtw89_chip_info *mac_reg = rtwdev->chip;
|
||||
u8 ch = rtwdev->hal.current_channel, ch_tmp;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u16 tx_en;
|
||||
u32 tx_en;
|
||||
u8 phy_map = rtw89_btc_phymap(rtwdev, phy, 0);
|
||||
s8 power;
|
||||
s16 xdbm;
|
||||
|
@ -3554,7 +3554,7 @@ static void _tssi_pre_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
|||
__func__, phy, power, xdbm);
|
||||
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_START);
|
||||
rtw89_mac_stop_sch_tx(rtwdev, phy, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, phy, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
_wait_rx_mode(rtwdev, _kpath(rtwdev, phy));
|
||||
tx_counter = rtw89_phy_read32_mask(rtwdev, R_TX_COUNTER, MASKLWORD);
|
||||
|
||||
|
@ -3600,7 +3600,7 @@ static void _tssi_pre_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
|||
|
||||
rtw8852a_bb_tx_mode_switch(rtwdev, phy, 0);
|
||||
|
||||
rtw89_mac_resume_sch_tx(rtwdev, phy, tx_en);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, phy, tx_en);
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_STOP);
|
||||
}
|
||||
|
||||
|
@ -3623,11 +3623,11 @@ void rtw8852a_dack(struct rtw89_dev *rtwdev)
|
|||
|
||||
void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u16 tx_en;
|
||||
u32 tx_en;
|
||||
u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
|
||||
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_START);
|
||||
rtw89_mac_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
_wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
|
||||
|
||||
_iqk_init(rtwdev);
|
||||
|
@ -3636,7 +3636,7 @@ void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
|
|||
else
|
||||
_iqk(rtwdev, phy_idx, false);
|
||||
|
||||
rtw89_mac_resume_sch_tx(rtwdev, phy_idx, tx_en);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP);
|
||||
}
|
||||
|
||||
|
@ -3648,33 +3648,33 @@ void rtw8852a_iqk_track(struct rtw89_dev *rtwdev)
|
|||
void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
|
||||
bool is_afe)
|
||||
{
|
||||
u16 tx_en;
|
||||
u32 tx_en;
|
||||
u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
|
||||
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_START);
|
||||
rtw89_mac_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
_wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
|
||||
|
||||
_rx_dck(rtwdev, phy_idx, is_afe);
|
||||
|
||||
rtw89_mac_resume_sch_tx(rtwdev, phy_idx, tx_en);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_STOP);
|
||||
}
|
||||
|
||||
void rtw8852a_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u16 tx_en;
|
||||
u32 tx_en;
|
||||
u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
|
||||
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_START);
|
||||
rtw89_mac_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
_wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
|
||||
|
||||
rtwdev->dpk.is_dpk_enable = true;
|
||||
rtwdev->dpk.is_dpk_reload_en = false;
|
||||
_dpk(rtwdev, phy_idx, false);
|
||||
|
||||
rtw89_mac_resume_sch_tx(rtwdev, phy_idx, tx_en);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
|
||||
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_STOP);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
#include "mac.h"
|
||||
#include "phy.h"
|
||||
#include "reg.h"
|
||||
#include "rtw8852c.h"
|
||||
|
||||
|
@ -44,6 +45,10 @@ static const struct rtw89_page_regs rtw8852c_page_regs = {
|
|||
.wp_page_info1 = R_AX_WP_PAGE_INFO1_V1,
|
||||
};
|
||||
|
||||
static const struct rtw89_reg_def rtw8852c_dcfo_comp = {
|
||||
R_DCFO_COMP_S0_V1, B_DCFO_COMP_S0_V1_MSK
|
||||
};
|
||||
|
||||
static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
u32 val32;
|
||||
|
@ -441,12 +446,54 @@ static void rtw8852c_power_trim(struct rtw89_dev *rtwdev)
|
|||
rtw8852c_pa_bias_trim(rtwdev);
|
||||
}
|
||||
|
||||
static
|
||||
void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
|
||||
s8 pw_ofst, enum rtw89_mac_idx mac_idx)
|
||||
{
|
||||
s8 pw_ofst_2tx;
|
||||
s8 val_1t;
|
||||
s8 val_2t;
|
||||
u32 reg;
|
||||
u8 i;
|
||||
|
||||
if (pw_ofst < -32 || pw_ofst > 31) {
|
||||
rtw89_warn(rtwdev, "[ULTB] Err pwr_offset=%d\n", pw_ofst);
|
||||
return;
|
||||
}
|
||||
val_1t = pw_ofst << 2;
|
||||
pw_ofst_2tx = max(pw_ofst - 3, -32);
|
||||
val_2t = pw_ofst_2tx << 2;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[ULTB] val_1tx=0x%x\n", val_1t);
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[ULTB] val_2tx=0x%x\n", val_2t);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
/* 1TX */
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg,
|
||||
B_AX_PWR_UL_TB_1T_V1_MASK << (8 * i),
|
||||
val_1t);
|
||||
/* 2TX */
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg,
|
||||
B_AX_PWR_UL_TB_2T_V1_MASK << (8 * i),
|
||||
val_2t);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct rtw89_chip_ops rtw8852c_chip_ops = {
|
||||
.read_efuse = rtw8852c_read_efuse,
|
||||
.read_phycap = rtw8852c_read_phycap,
|
||||
.power_trim = rtw8852c_power_trim,
|
||||
.read_rf = rtw89_phy_read_rf_v1,
|
||||
.write_rf = rtw89_phy_write_rf_v1,
|
||||
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
|
||||
.pwr_on_func = rtw8852c_pwr_on_func,
|
||||
.pwr_off_func = rtw8852c_pwr_off_func,
|
||||
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1,
|
||||
.mac_cfg_gnt = rtw89_mac_cfg_gnt_v1,
|
||||
.stop_sch_tx = rtw89_mac_stop_sch_tx_v1,
|
||||
.resume_sch_tx = rtw89_mac_resume_sch_tx_v1,
|
||||
};
|
||||
|
||||
const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||
|
@ -454,6 +501,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
|||
.ops = &rtw8852c_chip_ops,
|
||||
.fw_name = "rtw89/rtw8852c_fw.bin",
|
||||
.dle_mem = rtw8852c_dle_mem_pcie,
|
||||
.rf_base_addr = {0xe000, 0xf000},
|
||||
.pwr_on_seq = NULL,
|
||||
.pwr_off_seq = NULL,
|
||||
.sec_ctrl_efuse_size = 4,
|
||||
|
@ -470,6 +518,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
|||
.c2h_ctrl_reg = R_AX_C2HREG_CTRL_V1,
|
||||
.c2h_regs = rtw8852c_c2h_regs,
|
||||
.page_regs = &rtw8852c_page_regs,
|
||||
.dcfo_comp = &rtw8852c_dcfo_comp,
|
||||
.dcfo_comp_sft = 5,
|
||||
};
|
||||
EXPORT_SYMBOL(rtw8852c_chip_info);
|
||||
|
||||
|
|
|
@ -521,7 +521,7 @@ static int zd1201_setconfig(struct zd1201 *zd, int rid, const void *buf, int len
|
|||
zd->rxdatas = 0;
|
||||
zd->rxlen = 0;
|
||||
for (seq=0; len > 0; seq++) {
|
||||
request = kmalloc(16, gfp_mask);
|
||||
request = kzalloc(16, gfp_mask);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
urb = usb_alloc_urb(0, gfp_mask);
|
||||
|
@ -529,7 +529,6 @@ static int zd1201_setconfig(struct zd1201 *zd, int rid, const void *buf, int len
|
|||
kfree(request);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(request, 0, 16);
|
||||
reqlen = len>12 ? 12 : len;
|
||||
request[0] = ZD1201_USB_RESREQ;
|
||||
request[1] = seq;
|
||||
|
|
|
@ -4948,12 +4948,14 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
|
|||
* @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets
|
||||
* to countdown counters. This array can contain zero values which
|
||||
* should be ignored.
|
||||
* @mbssid_off: position of the multiple bssid element
|
||||
*/
|
||||
struct ieee80211_mutable_offsets {
|
||||
u16 tim_offset;
|
||||
u16 tim_length;
|
||||
|
||||
u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
u16 mbssid_off;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -159,8 +159,16 @@ struct rfkill_event_ext {
|
|||
* old behaviour for all userspace, unless it explicitly opts in to the
|
||||
* rules outlined here by using the new &struct rfkill_event_ext.
|
||||
*
|
||||
* Userspace using &struct rfkill_event_ext must adhere to the following
|
||||
* rules
|
||||
* Additionally, some other userspace (bluez, g-s-d) was reading with a
|
||||
* large size but as streaming reads rather than message-based, or with
|
||||
* too strict checks for the returned size. So eventually, we completely
|
||||
* reverted this, and extended messages need to be opted in to by using
|
||||
* an ioctl:
|
||||
*
|
||||
* ioctl(fd, RFKILL_IOCTL_MAX_SIZE, sizeof(struct rfkill_event_ext));
|
||||
*
|
||||
* Userspace using &struct rfkill_event_ext and the ioctl must adhere to
|
||||
* the following rules:
|
||||
*
|
||||
* 1. accept short writes, optionally using them to detect that it's
|
||||
* running on an older kernel;
|
||||
|
@ -175,6 +183,8 @@ struct rfkill_event_ext {
|
|||
#define RFKILL_IOC_MAGIC 'R'
|
||||
#define RFKILL_IOC_NOINPUT 1
|
||||
#define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
|
||||
#define RFKILL_IOC_MAX_SIZE 2
|
||||
#define RFKILL_IOCTL_MAX_SIZE _IOW(RFKILL_IOC_MAGIC, RFKILL_IOC_EXT_SIZE, __u32)
|
||||
|
||||
/* and that's all userspace gets */
|
||||
|
||||
|
|
|
@ -989,11 +989,29 @@ static int ieee80211_set_ftm_responder_params(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
|
||||
struct cfg80211_mbssid_elems *src)
|
||||
{
|
||||
int i, offset = 0;
|
||||
|
||||
for (i = 0; i < src->cnt; i++) {
|
||||
memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
|
||||
dst->elem[i].len = src->elem[i].len;
|
||||
dst->elem[i].data = pos + offset;
|
||||
offset += dst->elem[i].len;
|
||||
}
|
||||
dst->cnt = src->cnt;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_beacon_data *params,
|
||||
const struct ieee80211_csa_settings *csa,
|
||||
const struct ieee80211_color_change_settings *cca)
|
||||
{
|
||||
struct cfg80211_mbssid_elems *mbssid = NULL;
|
||||
struct beacon_data *new, *old;
|
||||
int new_head_len, new_tail_len;
|
||||
int size, err;
|
||||
|
@ -1021,6 +1039,17 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
size = sizeof(*new) + new_head_len + new_tail_len;
|
||||
|
||||
/* new or old multiple BSSID elements? */
|
||||
if (params->mbssid_ies) {
|
||||
mbssid = params->mbssid_ies;
|
||||
size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
|
||||
size += ieee80211_get_mbssid_beacon_len(mbssid);
|
||||
} else if (old && old->mbssid_ies) {
|
||||
mbssid = old->mbssid_ies;
|
||||
size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
|
||||
size += ieee80211_get_mbssid_beacon_len(mbssid);
|
||||
}
|
||||
|
||||
new = kzalloc(size, GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
|
@ -1029,12 +1058,23 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
/*
|
||||
* pointers go into the block we allocated,
|
||||
* memory is | beacon_data | head | tail |
|
||||
* memory is | beacon_data | head | tail | mbssid_ies
|
||||
*/
|
||||
new->head = ((u8 *) new) + sizeof(*new);
|
||||
new->tail = new->head + new_head_len;
|
||||
new->head_len = new_head_len;
|
||||
new->tail_len = new_tail_len;
|
||||
/* copy in optional mbssid_ies */
|
||||
if (mbssid) {
|
||||
u8 *pos = new->tail + new->tail_len;
|
||||
|
||||
new->mbssid_ies = (void *)pos;
|
||||
pos += struct_size(new->mbssid_ies, elem, mbssid->cnt);
|
||||
ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid);
|
||||
/* update bssid_indicator */
|
||||
sdata->vif.bss_conf.bssid_indicator =
|
||||
ilog2(__roundup_pow_of_two(mbssid->cnt + 1));
|
||||
}
|
||||
|
||||
if (csa) {
|
||||
new->cntdwn_current_counter = csa->count;
|
||||
|
@ -1332,8 +1372,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
if (sdata->u.ap.next_beacon) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
}
|
||||
|
||||
/* turn off carrier for this interface and dependent VLANs */
|
||||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
|
||||
|
@ -3135,12 +3178,24 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
|
|||
|
||||
len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
|
||||
beacon->proberesp_ies_len + beacon->assocresp_ies_len +
|
||||
beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
|
||||
beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len +
|
||||
ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
|
||||
|
||||
new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
|
||||
if (!new_beacon)
|
||||
return NULL;
|
||||
|
||||
if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) {
|
||||
new_beacon->mbssid_ies =
|
||||
kzalloc(struct_size(new_beacon->mbssid_ies,
|
||||
elem, beacon->mbssid_ies->cnt),
|
||||
GFP_KERNEL);
|
||||
if (!new_beacon->mbssid_ies) {
|
||||
kfree(new_beacon);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pos = (u8 *)(new_beacon + 1);
|
||||
if (beacon->head_len) {
|
||||
new_beacon->head_len = beacon->head_len;
|
||||
|
@ -3178,6 +3233,10 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
|
|||
memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
|
||||
pos += beacon->probe_resp_len;
|
||||
}
|
||||
if (beacon->mbssid_ies && beacon->mbssid_ies->cnt)
|
||||
pos += ieee80211_copy_mbssid_beacon(pos,
|
||||
new_beacon->mbssid_ies,
|
||||
beacon->mbssid_ies);
|
||||
|
||||
/* might copy -1, meaning no changes requested */
|
||||
new_beacon->ftm_responder = beacon->ftm_responder;
|
||||
|
@ -3200,9 +3259,31 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
|
|||
void ieee80211_csa_finish(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->csa_finalize_work);
|
||||
rcu_read_lock();
|
||||
|
||||
if (vif->mbssid_tx_vif == vif) {
|
||||
/* Trigger ieee80211_csa_finish() on the non-transmitting
|
||||
* interfaces when channel switch is received on
|
||||
* transmitting interface
|
||||
*/
|
||||
struct ieee80211_sub_if_data *iter;
|
||||
|
||||
list_for_each_entry_rcu(iter, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(iter))
|
||||
continue;
|
||||
|
||||
if (iter == sdata || iter->vif.mbssid_tx_vif != vif)
|
||||
continue;
|
||||
|
||||
ieee80211_queue_work(&iter->local->hw,
|
||||
&iter->csa_finalize_work);
|
||||
}
|
||||
}
|
||||
ieee80211_queue_work(&local->hw, &sdata->csa_finalize_work);
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
||||
|
@ -3227,8 +3308,11 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
case NL80211_IFTYPE_AP:
|
||||
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||
NULL, NULL);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
if (sdata->u.ap.next_beacon) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -3383,8 +3467,12 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
if ((params->n_counter_offsets_beacon >
|
||||
IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
|
||||
(params->n_counter_offsets_presp >
|
||||
IEEE80211_MAX_CNTDWN_COUNTERS_NUM))
|
||||
IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
csa.counter_offsets_beacon = params->counter_offsets_beacon;
|
||||
csa.counter_offsets_presp = params->counter_offsets_presp;
|
||||
|
@ -3394,7 +3482,9 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL);
|
||||
if (err < 0) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
return err;
|
||||
}
|
||||
*changed |= err;
|
||||
|
@ -3484,8 +3574,11 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
sdata->vif.color_change_active = false;
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
if (sdata->u.ap.next_beacon) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
}
|
||||
|
||||
cfg80211_color_change_aborted_notify(sdata->dev);
|
||||
}
|
||||
|
@ -4223,8 +4316,11 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||
NULL, NULL);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
if (sdata->u.ap.next_beacon) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -4267,7 +4363,11 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change,
|
||||
NULL, &color_change);
|
||||
if (err < 0) {
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
if (sdata->u.ap.next_beacon) {
|
||||
kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
*changed |= err;
|
||||
|
|
|
@ -257,6 +257,7 @@ struct beacon_data {
|
|||
struct ieee80211_meshconf_ie *meshconf;
|
||||
u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
u8 cntdwn_current_counter;
|
||||
struct cfg80211_mbssid_elems *mbssid_ies;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
|
@ -1083,6 +1084,20 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif)
|
|||
return shift;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems)
|
||||
{
|
||||
int i, len = 0;
|
||||
|
||||
if (!elems)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < elems->cnt; i++)
|
||||
len += elems->elem[i].len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
enum {
|
||||
IEEE80211_RX_MSG = 1,
|
||||
IEEE80211_TX_STATUS_MSG = 2,
|
||||
|
|
|
@ -4934,6 +4934,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
|
@ -4969,7 +4970,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* interface setup */
|
||||
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
||||
|
|
|
@ -5042,6 +5042,19 @@ ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
|
|||
IEEE80211_TX_CTL_FIRST_FRAGMENT;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!beacon->mbssid_ies)
|
||||
return;
|
||||
|
||||
for (i = 0; i < beacon->mbssid_ies->cnt; i++)
|
||||
skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
|
||||
beacon->mbssid_ies->elem[i].len);
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
|
@ -5055,6 +5068,7 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
|
|||
struct ieee80211_if_ap *ap = &sdata->u.ap;
|
||||
struct sk_buff *skb = NULL;
|
||||
u16 csa_off_base = 0;
|
||||
int mbssid_len;
|
||||
|
||||
if (beacon->cntdwn_counter_offsets[0]) {
|
||||
if (!is_template)
|
||||
|
@ -5064,11 +5078,12 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
/* headroom, head length,
|
||||
* tail length and maximum TIM length
|
||||
* tail length, maximum TIM length and multiple BSSID length
|
||||
*/
|
||||
mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
|
||||
skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
|
||||
beacon->tail_len + 256 +
|
||||
local->hw.extra_beacon_tailroom);
|
||||
local->hw.extra_beacon_tailroom + mbssid_len);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
|
@ -5082,6 +5097,11 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
|
|||
offs->tim_length = skb->len - beacon->head_len;
|
||||
offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
|
||||
|
||||
if (mbssid_len) {
|
||||
ieee80211_beacon_add_mbssid(skb, beacon);
|
||||
offs->mbssid_off = skb->len - mbssid_len;
|
||||
}
|
||||
|
||||
/* for AP the csa offsets are from tail */
|
||||
csa_off_base = skb->len;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ struct rfkill_data {
|
|||
struct mutex mtx;
|
||||
wait_queue_head_t read_wait;
|
||||
bool input_handler;
|
||||
u8 max_size;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1153,6 +1154,8 @@ static int rfkill_fop_open(struct inode *inode, struct file *file)
|
|||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->max_size = RFKILL_EVENT_SIZE_V1;
|
||||
|
||||
INIT_LIST_HEAD(&data->events);
|
||||
mutex_init(&data->mtx);
|
||||
init_waitqueue_head(&data->read_wait);
|
||||
|
@ -1235,6 +1238,7 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
|
|||
list);
|
||||
|
||||
sz = min_t(unsigned long, sizeof(ev->ev), count);
|
||||
sz = min_t(unsigned long, sz, data->max_size);
|
||||
ret = sz;
|
||||
if (copy_to_user(buf, &ev->ev, sz))
|
||||
ret = -EFAULT;
|
||||
|
@ -1249,6 +1253,7 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
|
|||
static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
struct rfkill_data *data = file->private_data;
|
||||
struct rfkill *rfkill;
|
||||
struct rfkill_event_ext ev;
|
||||
int ret;
|
||||
|
@ -1263,6 +1268,7 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
|
|||
* our API version even in a write() call, if it cares.
|
||||
*/
|
||||
count = min(count, sizeof(ev));
|
||||
count = min_t(size_t, count, data->max_size);
|
||||
if (copy_from_user(&ev, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -1322,31 +1328,47 @@ static int rfkill_fop_release(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
static long rfkill_fop_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct rfkill_data *data = file->private_data;
|
||||
int ret = -ENOSYS;
|
||||
u32 size;
|
||||
|
||||
if (_IOC_TYPE(cmd) != RFKILL_IOC_MAGIC)
|
||||
return -ENOSYS;
|
||||
|
||||
if (_IOC_NR(cmd) != RFKILL_IOC_NOINPUT)
|
||||
return -ENOSYS;
|
||||
|
||||
mutex_lock(&data->mtx);
|
||||
|
||||
if (!data->input_handler) {
|
||||
if (atomic_inc_return(&rfkill_input_disabled) == 1)
|
||||
printk(KERN_DEBUG "rfkill: input handler disabled\n");
|
||||
data->input_handler = true;
|
||||
switch (_IOC_NR(cmd)) {
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
case RFKILL_IOC_NOINPUT:
|
||||
if (!data->input_handler) {
|
||||
if (atomic_inc_return(&rfkill_input_disabled) == 1)
|
||||
printk(KERN_DEBUG "rfkill: input handler disabled\n");
|
||||
data->input_handler = true;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
#endif
|
||||
case RFKILL_IOC_MAX_SIZE:
|
||||
if (get_user(size, (__u32 __user *)arg)) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (size < RFKILL_EVENT_SIZE_V1 || size > U8_MAX) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
data->max_size = size;
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->mtx);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct file_operations rfkill_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -1355,10 +1377,8 @@ static const struct file_operations rfkill_fops = {
|
|||
.write = rfkill_fop_write,
|
||||
.poll = rfkill_fop_poll,
|
||||
.release = rfkill_fop_release,
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
.unlocked_ioctl = rfkill_fop_ioctl,
|
||||
.compat_ioctl = compat_ptr_ioctl,
|
||||
#endif
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue