mt76 patches for 5.20
- preparation for new chipset support - fixes - VHT/HE related improvements - ACPI SAR support -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCYswM/gAKCRDXfRQdAqdu 9e8MAKDE95xMfVuG+qUHYUnUiq0US5+z1ACeO4AQu0lHl73AgmsQwRp69/0v8+c= =OO4M -----END PGP SIGNATURE----- Merge tag 'mt76-for-kvalo-2022-07-11' of https://github.com/nbd168/wireless mt76 patches for 5.20 - preparation for new chipset support - fixes - VHT/HE related improvements - ACPI SAR support [kvalo@kernel.org: fix mac80211 API changes in start_ap() and stop_ap()]
This commit is contained in:
commit
30b5057339
@ -54,6 +54,16 @@ properties:
|
||||
reset-names:
|
||||
const: consys
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
description:
|
||||
Specify the consys clocks for mt7986.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mcu
|
||||
- const: ap2conn
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
@ -269,5 +279,8 @@ examples:
|
||||
<0x10003000 0x1000>,
|
||||
<0x11d10000 0x1000>;
|
||||
interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&topckgen 50>,
|
||||
<&topckgen 62>;
|
||||
clock-names = "mcu", "ap2conn";
|
||||
memory-region = <&wmcpu_emi>;
|
||||
};
|
||||
|
@ -349,8 +349,8 @@ error:
|
||||
|
||||
static int
|
||||
mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
enum mt76_txq_id qid, struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ieee80211_tx_status status = {
|
||||
.sta = sta,
|
||||
@ -406,7 +406,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
|
||||
dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
|
||||
ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info);
|
||||
dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
if (ret < 0)
|
||||
@ -791,10 +791,15 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
|
||||
mt76_worker_disable(&dev->tx_worker);
|
||||
netif_napi_del(&dev->tx_napi);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) {
|
||||
mt76_dma_tx_cleanup(dev, dev->phy.q_tx[i], true);
|
||||
if (dev->phy2)
|
||||
mt76_dma_tx_cleanup(dev, dev->phy2->q_tx[i], true);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
|
||||
struct mt76_phy *phy = dev->phys[i];
|
||||
int j;
|
||||
|
||||
if (!phy)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(phy->q_tx); j++)
|
||||
mt76_dma_tx_cleanup(dev, phy->q_tx[j], true);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->q_mcu); i++)
|
||||
|
@ -162,10 +162,13 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
|
||||
}
|
||||
|
||||
if (mt76_string_prop_find(country, dev->alpha2) ||
|
||||
mt76_string_prop_find(regd, region_name))
|
||||
mt76_string_prop_find(regd, region_name)) {
|
||||
of_node_put(np);
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
|
@ -178,6 +178,12 @@ static const struct cfg80211_sar_freq_ranges mt76_sar_freq_ranges[] = {
|
||||
{ .start_freq = 5350, .end_freq = 5470, },
|
||||
{ .start_freq = 5470, .end_freq = 5725, },
|
||||
{ .start_freq = 5725, .end_freq = 5950, },
|
||||
{ .start_freq = 5945, .end_freq = 6165, },
|
||||
{ .start_freq = 6165, .end_freq = 6405, },
|
||||
{ .start_freq = 6405, .end_freq = 6525, },
|
||||
{ .start_freq = 6525, .end_freq = 6705, },
|
||||
{ .start_freq = 6705, .end_freq = 6865, },
|
||||
{ .start_freq = 6865, .end_freq = 7125, },
|
||||
};
|
||||
|
||||
static const struct cfg80211_sar_capa mt76_sar_capa = {
|
||||
@ -210,6 +216,7 @@ static int mt76_led_init(struct mt76_dev *dev)
|
||||
if (!of_property_read_u32(np, "led-sources", &led_pin))
|
||||
dev->led_pin = led_pin;
|
||||
dev->led_al = of_property_read_bool(np, "led-active-low");
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
return led_classdev_register(dev->dev, &dev->led_cdev);
|
||||
@ -260,6 +267,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
|
||||
}
|
||||
vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
|
||||
vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
|
||||
vht_cap->vht_mcs.tx_highest |=
|
||||
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
|
||||
}
|
||||
|
||||
void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)
|
||||
@ -444,7 +453,7 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
||||
|
||||
struct mt76_phy *
|
||||
mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
|
||||
const struct ieee80211_ops *ops)
|
||||
const struct ieee80211_ops *ops, u8 band_idx)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
unsigned int phy_size;
|
||||
@ -459,6 +468,7 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
|
||||
phy->dev = dev;
|
||||
phy->hw = hw;
|
||||
phy->priv = hw->priv + phy_size;
|
||||
phy->band_idx = band_idx;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||
hw->wiphy->interface_modes =
|
||||
@ -511,7 +521,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
phy->dev->phy2 = phy;
|
||||
phy->dev->phys[phy->band_idx] = phy;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -523,7 +533,7 @@ void mt76_unregister_phy(struct mt76_phy *phy)
|
||||
|
||||
mt76_tx_status_check(dev, true);
|
||||
ieee80211_unregister_hw(phy->hw);
|
||||
dev->phy2 = NULL;
|
||||
dev->phys[phy->band_idx] = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
|
||||
|
||||
@ -550,6 +560,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
|
||||
phy = &dev->phy;
|
||||
phy->dev = dev;
|
||||
phy->hw = hw;
|
||||
phy->band_idx = MT_BAND0;
|
||||
dev->phys[phy->band_idx] = phy;
|
||||
|
||||
spin_lock_init(&dev->rx_lock);
|
||||
spin_lock_init(&dev->lock);
|
||||
@ -731,7 +743,7 @@ static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q,
|
||||
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy);
|
||||
struct mt76_phy *phy = mt76_dev_phy(dev, status->phy_idx);
|
||||
|
||||
if (!test_bit(MT76_STATE_RUNNING, &phy->state)) {
|
||||
dev_kfree_skb(skb);
|
||||
@ -1007,10 +1019,10 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
sizeof(mstat.chain_signal));
|
||||
|
||||
*sta = wcid_to_sta(mstat.wcid);
|
||||
*hw = mt76_phy_hw(dev, mstat.ext_phy);
|
||||
*hw = mt76_phy_hw(dev, mstat.phy_idx);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
mt76_check_ccmp_pn(struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
@ -1020,10 +1032,13 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
|
||||
int ret;
|
||||
|
||||
if (!(status->flag & RX_FLAG_DECRYPTED))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (status->flag & RX_FLAG_ONLY_MONITOR)
|
||||
return;
|
||||
|
||||
if (!wcid || !wcid->rx_check_pn)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
security_idx = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (status->flag & RX_FLAG_8023)
|
||||
@ -1037,7 +1052,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
|
||||
*/
|
||||
if (ieee80211_is_frag(hdr) &&
|
||||
!ieee80211_is_first_frag(hdr->frame_control))
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* IEEE 802.11-2020, 12.5.3.4.4 "PN and replay detection" c):
|
||||
@ -1054,15 +1069,15 @@ skip_hdr_check:
|
||||
BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
|
||||
ret = memcmp(status->iv, wcid->rx_key_pn[security_idx],
|
||||
sizeof(status->iv));
|
||||
if (ret <= 0)
|
||||
return -EINVAL; /* replay */
|
||||
if (ret <= 0) {
|
||||
status->flag |= RX_FLAG_ONLY_MONITOR;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(wcid->rx_key_pn[security_idx], status->iv, sizeof(status->iv));
|
||||
|
||||
if (status->flag & RX_FLAG_IV_STRIPPED)
|
||||
status->flag |= RX_FLAG_PN_VALIDATED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1167,7 +1182,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
bool ps;
|
||||
|
||||
hw = mt76_phy_hw(dev, status->ext_phy);
|
||||
hw = mt76_phy_hw(dev, status->phy_idx);
|
||||
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid &&
|
||||
!(status->flag & RX_FLAG_8023)) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
|
||||
@ -1235,11 +1250,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
|
||||
while ((skb = __skb_dequeue(frames)) != NULL) {
|
||||
struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
|
||||
|
||||
if (mt76_check_ccmp_pn(skb)) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
mt76_check_ccmp_pn(skb);
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
mt76_rx_convert(dev, skb, &hw, &sta);
|
||||
ieee80211_rx_list(hw, sta, skb, &list);
|
||||
@ -1285,10 +1296,11 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
|
||||
EXPORT_SYMBOL_GPL(mt76_rx_poll_complete);
|
||||
|
||||
static int
|
||||
mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool ext_phy)
|
||||
mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@ -1309,9 +1321,9 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
if (ext_phy)
|
||||
if (phy->band_idx == MT_BAND1)
|
||||
mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx);
|
||||
wcid->ext_phy = ext_phy;
|
||||
wcid->phy_idx = phy->band_idx;
|
||||
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
||||
|
||||
mt76_packet_id_init(wcid);
|
||||
@ -1356,11 +1368,10 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt76_phy *phy = hw->priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
|
||||
if (old_state == IEEE80211_STA_NOTEXIST &&
|
||||
new_state == IEEE80211_STA_NONE)
|
||||
return mt76_sta_add(dev, vif, sta, ext_phy);
|
||||
return mt76_sta_add(phy, vif, sta);
|
||||
|
||||
if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC &&
|
||||
|
@ -7,17 +7,19 @@
|
||||
|
||||
struct sk_buff *
|
||||
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len, gfp_t gfp)
|
||||
int len, int data_len, gfp_t gfp)
|
||||
{
|
||||
const struct mt76_mcu_ops *ops = dev->mcu_ops;
|
||||
int length = ops->headroom + data_len + ops->tailroom;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(length, gfp);
|
||||
len = max_t(int, len, data_len);
|
||||
len = ops->headroom + len + ops->tailroom;
|
||||
|
||||
skb = alloc_skb(len, gfp);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
memset(skb->head, 0, length);
|
||||
memset(skb->head, 0, len);
|
||||
skb_reserve(skb, ops->headroom);
|
||||
|
||||
if (data && data_len)
|
||||
|
@ -99,12 +99,21 @@ enum mt76_rxq_id {
|
||||
MT_RXQ_MAIN,
|
||||
MT_RXQ_MCU,
|
||||
MT_RXQ_MCU_WA,
|
||||
MT_RXQ_EXT,
|
||||
MT_RXQ_EXT_WA,
|
||||
MT_RXQ_BAND1,
|
||||
MT_RXQ_BAND1_WA,
|
||||
MT_RXQ_MAIN_WA,
|
||||
MT_RXQ_BAND2,
|
||||
MT_RXQ_BAND2_WA,
|
||||
__MT_RXQ_MAX
|
||||
};
|
||||
|
||||
enum mt76_band_id {
|
||||
MT_BAND0,
|
||||
MT_BAND1,
|
||||
MT_BAND2,
|
||||
__MT_MAX_BAND
|
||||
};
|
||||
|
||||
enum mt76_cipher_type {
|
||||
MT_CIPHER_NONE,
|
||||
MT_CIPHER_WEP40,
|
||||
@ -185,7 +194,6 @@ struct mt76_queue {
|
||||
|
||||
u8 buf_offset;
|
||||
u8 hw_idx;
|
||||
u8 qid;
|
||||
u8 flags;
|
||||
|
||||
u32 wed_regs;
|
||||
@ -223,8 +231,8 @@ struct mt76_queue_ops {
|
||||
u32 ring_base);
|
||||
|
||||
int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
enum mt76_txq_id qid, struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta);
|
||||
|
||||
int (*tx_queue_skb_raw)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, u32 tx_info);
|
||||
@ -254,7 +262,7 @@ enum mt76_wcid_flags {
|
||||
#define MT76_N_WCIDS 544
|
||||
|
||||
/* stored in ieee80211_tx_info::hw_queue */
|
||||
#define MT_TX_HW_QUEUE_EXT_PHY BIT(3)
|
||||
#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)
|
||||
|
||||
DECLARE_EWMA(signal, 10, 8);
|
||||
|
||||
@ -279,8 +287,8 @@ struct mt76_wcid {
|
||||
u8 hw_key_idx2;
|
||||
|
||||
u8 sta:1;
|
||||
u8 ext_phy:1;
|
||||
u8 amsdu:1;
|
||||
u8 phy_idx:2;
|
||||
|
||||
u8 rx_check_pn;
|
||||
u8 rx_key_pn[IEEE80211_NUM_TIDS + 1][6];
|
||||
@ -573,7 +581,7 @@ struct mt76_rx_status {
|
||||
|
||||
u8 iv[6];
|
||||
|
||||
u8 ext_phy:1;
|
||||
u8 phy_idx:2;
|
||||
u8 aggr:1;
|
||||
u8 qos_ctl;
|
||||
u16 seqno;
|
||||
@ -660,6 +668,7 @@ struct mt76_phy {
|
||||
void *priv;
|
||||
|
||||
unsigned long state;
|
||||
u8 band_idx;
|
||||
|
||||
struct mt76_queue *q_tx[__MT_TXQ_MAX];
|
||||
|
||||
@ -699,8 +708,7 @@ struct mt76_phy {
|
||||
|
||||
struct mt76_dev {
|
||||
struct mt76_phy phy; /* must be first */
|
||||
|
||||
struct mt76_phy *phy2;
|
||||
struct mt76_phy *phys[__MT_MAX_BAND];
|
||||
|
||||
struct ieee80211_hw *hw;
|
||||
|
||||
@ -885,16 +893,6 @@ extern struct ieee80211_rate mt76_rates[12];
|
||||
|
||||
#define mt76_hw(dev) (dev)->mphy.hw
|
||||
|
||||
static inline struct ieee80211_hw *
|
||||
mt76_wcid_hw(struct mt76_dev *dev, u16 wcid)
|
||||
{
|
||||
if (wcid <= MT76_N_WCIDS &&
|
||||
mt76_wcid_mask_test(dev->wcid_phy_mask, wcid))
|
||||
return dev->phy2->hw;
|
||||
|
||||
return dev->phy.hw;
|
||||
}
|
||||
|
||||
bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
int timeout);
|
||||
|
||||
@ -945,7 +943,8 @@ void mt76_free_device(struct mt76_dev *dev);
|
||||
void mt76_unregister_phy(struct mt76_phy *phy);
|
||||
|
||||
struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
|
||||
const struct ieee80211_ops *ops);
|
||||
const struct ieee80211_ops *ops,
|
||||
u8 band_idx);
|
||||
int mt76_register_phy(struct mt76_phy *phy, bool vht,
|
||||
struct ieee80211_rate *rates, int n_rates);
|
||||
|
||||
@ -977,7 +976,6 @@ static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
|
||||
q->qid = qid;
|
||||
phy->q_tx[qid] = q;
|
||||
|
||||
return 0;
|
||||
@ -992,24 +990,25 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx,
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
|
||||
q->qid = __MT_TXQ_MAX + qid;
|
||||
dev->q_mcu[qid] = q;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct mt76_phy *
|
||||
mt76_dev_phy(struct mt76_dev *dev, bool phy_ext)
|
||||
mt76_dev_phy(struct mt76_dev *dev, u8 phy_idx)
|
||||
{
|
||||
if (phy_ext && dev->phy2)
|
||||
return dev->phy2;
|
||||
if ((phy_idx == MT_BAND1 && dev->phys[phy_idx]) ||
|
||||
(phy_idx == MT_BAND2 && dev->phys[phy_idx]))
|
||||
return dev->phys[phy_idx];
|
||||
|
||||
return &dev->phy;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_hw *
|
||||
mt76_phy_hw(struct mt76_dev *dev, bool phy_ext)
|
||||
mt76_phy_hw(struct mt76_dev *dev, u8 phy_idx)
|
||||
{
|
||||
return mt76_dev_phy(dev, phy_ext)->hw;
|
||||
return mt76_dev_phy(dev, phy_idx)->hw;
|
||||
}
|
||||
|
||||
static inline u8 *
|
||||
@ -1120,13 +1119,17 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
|
||||
struct ieee80211_hw **hw)
|
||||
{
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
if (skb == dev->phy.test.tx_skb)
|
||||
*hw = dev->phy.hw;
|
||||
else if (dev->phy2 && skb == dev->phy2->test.tx_skb)
|
||||
*hw = dev->phy2->hw;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
|
||||
struct mt76_phy *phy = dev->phys[i];
|
||||
|
||||
if (phy && skb == phy->test.tx_skb) {
|
||||
*hw = dev->phys[i]->hw;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@ -1242,12 +1245,10 @@ static inline struct ieee80211_hw *
|
||||
mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hw *hw = dev->phy.hw;
|
||||
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
|
||||
struct ieee80211_hw *hw = mt76_phy_hw(dev, phy_idx);
|
||||
|
||||
if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2)
|
||||
hw = dev->phy2->hw;
|
||||
|
||||
info->hw_queue &= ~MT_TX_HW_QUEUE_EXT_PHY;
|
||||
info->hw_queue &= ~MT_TX_HW_QUEUE_PHY;
|
||||
|
||||
return hw;
|
||||
}
|
||||
@ -1346,12 +1347,12 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
|
||||
|
||||
struct sk_buff *
|
||||
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len, gfp_t gfp);
|
||||
int len, int data_len, gfp_t gfp);
|
||||
static inline struct sk_buff *
|
||||
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len)
|
||||
{
|
||||
return __mt76_mcu_msg_alloc(dev, data, data_len, GFP_KERNEL);
|
||||
return __mt76_mcu_msg_alloc(dev, data, data_len, data_len, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
|
||||
|
@ -24,8 +24,8 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], skb,
|
||||
&mvif->sta.wcid, NULL);
|
||||
mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
|
||||
MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
|
||||
|
||||
spin_lock_bh(&dev->ps_lock);
|
||||
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
|
||||
@ -123,7 +123,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
|
||||
|
||||
mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL);
|
||||
mt76_tx_queue_skb(dev, q, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL);
|
||||
}
|
||||
mt76_queue_kick(dev, q);
|
||||
spin_unlock(&q->lock);
|
||||
|
@ -44,7 +44,7 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
|
||||
static int
|
||||
mt7615_init_tx_queues(struct mt7615_dev *dev)
|
||||
{
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7615_TXQ_FWDL,
|
||||
MT7615_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
|
||||
@ -54,14 +54,11 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
|
||||
if (!is_mt7615(&dev->mt76))
|
||||
return mt7622_init_tx_queues_multi(dev);
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE, 0);
|
||||
ret = mt76_connac_init_tx_queues(&dev->mphy, 0, MT7615_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 1; i <= MT_TXQ_PSD ; i++)
|
||||
dev->mphy.q_tx[i] = dev->mphy.q_tx[0];
|
||||
|
||||
return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7615_TXQ_MCU,
|
||||
MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
|
||||
}
|
||||
|
@ -401,6 +401,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
|
||||
if (is_mt7615(&phy->dev->mt76))
|
||||
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
|
||||
@ -458,7 +459,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
|
||||
return 0;
|
||||
|
||||
mt7615_cap_dbdc_enable(dev);
|
||||
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops);
|
||||
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1);
|
||||
if (!mphy)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -508,7 +509,7 @@ EXPORT_SYMBOL_GPL(mt7615_register_ext_phy);
|
||||
void mt7615_unregister_ext_phy(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt7615_phy *phy = mt7615_ext_phy(dev);
|
||||
struct mt76_phy *mphy = dev->mt76.phy2;
|
||||
struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (!phy)
|
||||
return;
|
||||
|
@ -109,6 +109,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
|
||||
|
||||
void mt7615_mac_reset_counters(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
@ -118,8 +119,8 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev)
|
||||
|
||||
memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats));
|
||||
dev->mt76.phy.survey_time = ktime_get_boottime();
|
||||
if (dev->mt76.phy2)
|
||||
dev->mt76.phy2->survey_time = ktime_get_boottime();
|
||||
if (mphy_ext)
|
||||
mphy_ext->survey_time = ktime_get_boottime();
|
||||
|
||||
/* reset airtime counters */
|
||||
mt76_rr(dev, MT_MIB_SDR9(0));
|
||||
@ -336,9 +337,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt7615_phy *phy = &dev->phy;
|
||||
struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct mt7615_phy *phy2;
|
||||
__le32 *rxd = (__le32 *)skb->data;
|
||||
u32 rxd0 = le32_to_cpu(rxd[0]);
|
||||
u32 rxd1 = le32_to_cpu(rxd[1]);
|
||||
@ -355,6 +356,8 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1);
|
||||
|
||||
phy2 = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
|
||||
if (!phy2)
|
||||
phy_idx = 0;
|
||||
else if (phy2->chfreq == phy->chfreq)
|
||||
@ -498,9 +501,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (phy_idx == 1 && phy2) {
|
||||
mphy = dev->mt76.phy2;
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
phy = phy2;
|
||||
status->ext_phy = true;
|
||||
status->phy_idx = phy_idx;
|
||||
}
|
||||
|
||||
if (!mt7615_firmware_offload(dev) && chfreq != phy->chfreq)
|
||||
@ -717,13 +720,14 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev,
|
||||
int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta, int pid,
|
||||
struct ieee80211_key_conf *key, bool beacon)
|
||||
struct ieee80211_key_conf *key,
|
||||
enum mt76_txq_id qid, bool beacon)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *rate = &info->control.rates[0];
|
||||
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
|
||||
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
bool is_mmio = mt76_is_mmio(&dev->mt76);
|
||||
@ -746,18 +750,18 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
|
||||
tx_count = msta->rate_count;
|
||||
}
|
||||
|
||||
if (ext_phy && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (phy_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
|
||||
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
|
||||
|
||||
if (beacon) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = ext_phy ? MT_LMAC_BCN1 : MT_LMAC_BCN0;
|
||||
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
|
||||
q_idx = phy_idx ? MT_LMAC_BCN1 : MT_LMAC_BCN0;
|
||||
} else if (qid >= MT_TXQ_PSD) {
|
||||
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
|
||||
q_idx = ext_phy ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0;
|
||||
q_idx = phy_idx ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0;
|
||||
} else {
|
||||
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
|
||||
q_idx = wmm_idx * MT7615_MAX_WMM_SETS +
|
||||
@ -876,60 +880,6 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_mac_write_txwi);
|
||||
|
||||
static void
|
||||
mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < txp->nbuf; i++)
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
|
||||
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp)
|
||||
{
|
||||
u32 last_mask;
|
||||
int i;
|
||||
|
||||
last_mask = is_mt7663(dev) ? MT_TXD_LEN_LAST : MT_TXD_LEN_MSDU_LAST;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) {
|
||||
struct mt7615_txp_ptr *ptr = &txp->ptr[i];
|
||||
bool last;
|
||||
u16 len;
|
||||
|
||||
len = le16_to_cpu(ptr->len0);
|
||||
last = len & last_mask;
|
||||
len &= MT_TXD_LEN_MASK;
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len,
|
||||
DMA_TO_DEVICE);
|
||||
if (last)
|
||||
break;
|
||||
|
||||
len = le16_to_cpu(ptr->len1);
|
||||
last = len & last_mask;
|
||||
len &= MT_TXD_LEN_MASK;
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len,
|
||||
DMA_TO_DEVICE);
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
|
||||
struct mt76_txwi_cache *t)
|
||||
{
|
||||
struct mt7615_txp_common *txp;
|
||||
|
||||
txp = mt7615_txwi_to_txp(dev, t);
|
||||
if (is_mt7615(dev))
|
||||
mt7615_txp_skb_unmap_fw(dev, &txp->fw);
|
||||
else
|
||||
mt7615_txp_skb_unmap_hw(dev, &txp->hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_txp_skb_unmap);
|
||||
|
||||
bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask)
|
||||
{
|
||||
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
|
||||
@ -1439,8 +1389,8 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
|
||||
if (sta->rate_probe) {
|
||||
struct mt7615_phy *phy = &dev->phy;
|
||||
|
||||
if (sta->wcid.ext_phy && dev->mt76.phy2)
|
||||
phy = dev->mt76.phy2->priv;
|
||||
if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1])
|
||||
phy = dev->mt76.phys[MT_BAND1]->priv;
|
||||
|
||||
mt7615_mac_set_rates(phy, sta, NULL, sta->rates);
|
||||
}
|
||||
@ -1482,8 +1432,8 @@ out:
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
mphy = &dev->mphy;
|
||||
if (sta->wcid.ext_phy && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
@ -1590,8 +1540,8 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
|
||||
if (wcidx >= MT7615_WTBL_STA || !sta)
|
||||
goto out;
|
||||
|
||||
if (wcid->ext_phy && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (wcid->phy_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (mt7615_fill_txs(dev, msta, &info, txs_data))
|
||||
ieee80211_tx_status_noskb(mphy->hw, sta, &info);
|
||||
@ -1608,7 +1558,7 @@ mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi)
|
||||
u32 val;
|
||||
u8 wcid;
|
||||
|
||||
mt7615_txp_skb_unmap(mdev, txwi);
|
||||
mt76_connac_txp_skb_unmap(mdev, txwi);
|
||||
if (!txwi->skb)
|
||||
goto out;
|
||||
|
||||
@ -1638,7 +1588,8 @@ mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
|
||||
|
||||
static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
|
||||
{
|
||||
struct mt7615_tx_free *free = (struct mt7615_tx_free *)data;
|
||||
struct mt76_connac_tx_free *free = data;
|
||||
void *tx_token = data + sizeof(*free);
|
||||
void *end = data + len;
|
||||
u8 i, count;
|
||||
|
||||
@ -1652,7 +1603,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
|
||||
|
||||
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT);
|
||||
if (is_mt7615(&dev->mt76)) {
|
||||
__le16 *token = &free->token[0];
|
||||
__le16 *token = tx_token;
|
||||
|
||||
if (WARN_ON_ONCE((void *)&token[count] > end))
|
||||
return;
|
||||
@ -1660,7 +1611,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
|
||||
for (i = 0; i < count; i++)
|
||||
mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i]));
|
||||
} else {
|
||||
__le32 *token = (__le32 *)&free->token[0];
|
||||
__le32 *token = tx_token;
|
||||
|
||||
if (WARN_ON_ONCE((void *)&token[count] > end))
|
||||
return;
|
||||
@ -2007,6 +1958,7 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)
|
||||
static void mt7615_update_survey(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1];
|
||||
ktime_t cur_time;
|
||||
|
||||
/* MT7615 can only update both phys simultaneously
|
||||
@ -2014,14 +1966,14 @@ static void mt7615_update_survey(struct mt7615_dev *dev)
|
||||
*/
|
||||
|
||||
mt7615_phy_update_channel(&mdev->phy, 0);
|
||||
if (mdev->phy2)
|
||||
mt7615_phy_update_channel(mdev->phy2, 1);
|
||||
if (mphy_ext)
|
||||
mt7615_phy_update_channel(mphy_ext, 1);
|
||||
|
||||
cur_time = ktime_get_boottime();
|
||||
|
||||
mt76_update_survey_active_time(&mdev->phy, cur_time);
|
||||
if (mdev->phy2)
|
||||
mt76_update_survey_active_time(mdev->phy2, cur_time);
|
||||
if (mphy_ext)
|
||||
mt76_update_survey_active_time(mphy_ext, cur_time);
|
||||
|
||||
/* reset obss airtime */
|
||||
mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);
|
||||
@ -2094,8 +2046,10 @@ void mt7615_pm_wake_work(struct work_struct *work)
|
||||
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
|
||||
mt76_worker_schedule(&mdev->sdio.txrx_worker);
|
||||
} else {
|
||||
local_bh_disable();
|
||||
mt76_for_each_q_rx(mdev, i)
|
||||
napi_schedule(&mdev->napi[i]);
|
||||
local_bh_enable();
|
||||
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
|
||||
mt76_queue_tx_cleanup(dev, mdev->q_mcu[MT_MCUQ_WM],
|
||||
false);
|
||||
@ -2282,6 +2236,7 @@ mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)
|
||||
|
||||
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
enum mt76_dfs_state dfs_state, prev_state;
|
||||
@ -2292,13 +2247,13 @@ int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy)
|
||||
|
||||
prev_state = phy->mt76->dfs_state;
|
||||
dfs_state = mt76_phy_dfs_state(phy->mt76);
|
||||
if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
|
||||
dfs_state < MT_DFS_STATE_CAC)
|
||||
dfs_state = MT_DFS_STATE_ACTIVE;
|
||||
|
||||
if (prev_state == dfs_state)
|
||||
return 0;
|
||||
|
||||
if (prev_state == MT_DFS_STATE_UNKNOWN)
|
||||
mt7615_dfs_stop_radar_detector(phy);
|
||||
|
||||
if (dfs_state == MT_DFS_STATE_DISABLED)
|
||||
goto stop;
|
||||
|
||||
|
@ -165,12 +165,6 @@ enum tx_phy_bandwidth {
|
||||
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
|
||||
#define MT_CT_INFO_HSR2_TX BIT(4)
|
||||
|
||||
#define MT_TXD_SIZE (8 * 4)
|
||||
|
||||
#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
|
||||
#define MT_USB_HDR_SIZE 4
|
||||
#define MT_USB_TAIL_SIZE 4
|
||||
|
||||
#define MT_TXD0_P_IDX BIT(31)
|
||||
#define MT_TXD0_Q_IDX GENMASK(30, 26)
|
||||
#define MT_TXD0_UDP_TCP_SUM BIT(24)
|
||||
@ -250,56 +244,6 @@ enum tx_phy_bandwidth {
|
||||
#define MT_TX_RATE_MODE GENMASK(8, 6)
|
||||
#define MT_TX_RATE_IDX GENMASK(5, 0)
|
||||
|
||||
#define MT_TXP_MAX_BUF_NUM 6
|
||||
#define MT_HW_TXP_MAX_MSDU_NUM 4
|
||||
#define MT_HW_TXP_MAX_BUF_NUM 4
|
||||
|
||||
#define MT_MSDU_ID_VALID BIT(15)
|
||||
|
||||
#define MT_TXD_LEN_MASK GENMASK(11, 0)
|
||||
#define MT_TXD_LEN_MSDU_LAST BIT(14)
|
||||
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
|
||||
/* mt7663 */
|
||||
#define MT_TXD_LEN_LAST BIT(15)
|
||||
|
||||
struct mt7615_txp_ptr {
|
||||
__le32 buf0;
|
||||
__le16 len0;
|
||||
__le16 len1;
|
||||
__le32 buf1;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7615_hw_txp {
|
||||
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
|
||||
struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7615_fw_txp {
|
||||
__le16 flags;
|
||||
__le16 token;
|
||||
u8 bss_idx;
|
||||
u8 rept_wds_wcid;
|
||||
u8 rsv;
|
||||
u8 nbuf;
|
||||
__le32 buf[MT_TXP_MAX_BUF_NUM];
|
||||
__le16 len[MT_TXP_MAX_BUF_NUM];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7615_txp_common {
|
||||
union {
|
||||
struct mt7615_fw_txp fw;
|
||||
struct mt7615_hw_txp hw;
|
||||
};
|
||||
};
|
||||
|
||||
struct mt7615_tx_free {
|
||||
__le16 rx_byte_cnt;
|
||||
__le16 ctrl;
|
||||
u8 txd_cnt;
|
||||
u8 rsv[3];
|
||||
__le16 token[];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0)
|
||||
|
||||
#define MT_TXS0_PID GENMASK(31, 24)
|
||||
@ -385,19 +329,6 @@ struct mt7615_dfs_radar_spec {
|
||||
struct mt7615_dfs_pattern radar_pattern[16];
|
||||
};
|
||||
|
||||
static inline struct mt7615_txp_common *
|
||||
mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
u8 *txwi;
|
||||
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
txwi = mt76_get_txwi_ptr(dev, t);
|
||||
|
||||
return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE);
|
||||
}
|
||||
|
||||
static inline u32 mt7615_mac_wtbl_addr(struct mt7615_dev *dev, int wcid)
|
||||
{
|
||||
return MT_WTBL_BASE(dev) + wcid * MT_WTBL_ENTRY_SIZE;
|
||||
|
@ -224,7 +224,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
INIT_LIST_HEAD(&mvif->sta.poll_list);
|
||||
mvif->sta.wcid.idx = idx;
|
||||
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
|
||||
@ -282,26 +282,6 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
|
||||
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
|
||||
}
|
||||
|
||||
static void mt7615_init_dfs_state(struct mt7615_phy *phy)
|
||||
{
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
struct ieee80211_hw *hw = mphy->hw;
|
||||
struct cfg80211_chan_def *chandef = &hw->conf.chandef;
|
||||
|
||||
if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
return;
|
||||
|
||||
if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
|
||||
!(mphy->chandef.chan->flags & IEEE80211_CHAN_RADAR))
|
||||
return;
|
||||
|
||||
if (mphy->chandef.chan->center_freq == chandef->chan->center_freq &&
|
||||
mphy->chandef.width == chandef->width)
|
||||
return;
|
||||
|
||||
phy->dfs_state = -1;
|
||||
}
|
||||
|
||||
int mt7615_set_channel(struct mt7615_phy *phy)
|
||||
{
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
@ -314,7 +294,6 @@ int mt7615_set_channel(struct mt7615_phy *phy)
|
||||
|
||||
set_bit(MT76_RESET, &phy->mt76->state);
|
||||
|
||||
mt7615_init_dfs_state(phy);
|
||||
mt76_set_channel(phy->mt76);
|
||||
|
||||
if (is_mt7615(&dev->mt76) && dev->flash_eeprom) {
|
||||
@ -651,7 +630,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
msta->vif = mvif;
|
||||
msta->wcid.sta = 1;
|
||||
msta->wcid.idx = idx;
|
||||
msta->wcid.ext_phy = mvif->mt76.band_idx;
|
||||
msta->wcid.phy_idx = mvif->mt76.band_idx;
|
||||
|
||||
phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
|
||||
err = mt76_connac_pm_wake(phy->mt76, &dev->pm);
|
||||
|
@ -40,18 +40,6 @@ struct mt7615_fw_trailer {
|
||||
#define FW_START_DLYCAL BIT(1)
|
||||
#define FW_START_WORKING_PDA_CR4 BIT(2)
|
||||
|
||||
struct mt7663_fw_trailer {
|
||||
u8 chip_id;
|
||||
u8 eco_code;
|
||||
u8 n_region;
|
||||
u8 format_ver;
|
||||
u8 format_flag;
|
||||
u8 reserv[2];
|
||||
char fw_ver[10];
|
||||
char build_date[15];
|
||||
__le32 crc;
|
||||
} __packed;
|
||||
|
||||
struct mt7663_fw_buf {
|
||||
__le32 crc;
|
||||
__le32 d_img_size;
|
||||
@ -350,10 +338,11 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)
|
||||
}
|
||||
|
||||
mt7622_trigger_hif_int(dev, false);
|
||||
|
||||
pm->stats.last_doze_event = jiffies;
|
||||
pm->stats.awake_time += pm->stats.last_doze_event -
|
||||
pm->stats.last_wake_event;
|
||||
if (!err) {
|
||||
pm->stats.last_doze_event = jiffies;
|
||||
pm->stats.awake_time += pm->stats.last_doze_event -
|
||||
pm->stats.last_wake_event;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&pm->mutex);
|
||||
|
||||
@ -380,7 +369,7 @@ mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
return;
|
||||
|
||||
if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
|
||||
mphy = dev->mt76.phy2;
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
@ -399,8 +388,11 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
!r->constant_prf_detected && !r->staggered_prf_detected)
|
||||
return;
|
||||
|
||||
if (r->band_idx && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (r->band_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
|
||||
return;
|
||||
|
||||
ieee80211_radar_detected(mphy->hw);
|
||||
dev->hw_pattern++;
|
||||
@ -456,8 +448,8 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
struct mt7615_phy *phy;
|
||||
struct mt76_phy *mphy;
|
||||
|
||||
if (*seq_num & BIT(7) && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (*seq_num & BIT(7) && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
else
|
||||
mphy = &dev->mt76.phy;
|
||||
|
||||
@ -482,8 +474,8 @@ mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
|
||||
event = (struct mt7615_roc_tlv *)skb->data;
|
||||
|
||||
if (event->dbdc_band && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (event->dbdc_band && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
else
|
||||
mphy = &dev->mt76.phy;
|
||||
|
||||
@ -507,8 +499,8 @@ mt7615_mcu_beacon_loss_event(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
|
||||
event = (struct mt76_connac_beacon_loss_event *)skb->data;
|
||||
if (band_idx && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (band_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
else
|
||||
mphy = &dev->mt76.phy;
|
||||
|
||||
@ -528,8 +520,8 @@ mt7615_mcu_bss_event(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
|
||||
event = (struct mt76_connac_mcu_bss_event *)skb->data;
|
||||
|
||||
if (band_idx && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if (band_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
else
|
||||
mphy = &dev->mt76.phy;
|
||||
|
||||
@ -716,13 +708,11 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mvif->mt76.band_idx) {
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
}
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mvif->mt76.band_idx);
|
||||
|
||||
mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL,
|
||||
0, NULL, true);
|
||||
0, NULL, 0, true);
|
||||
memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);
|
||||
req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
|
||||
@ -855,6 +845,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
struct wtbl_req_hdr *wtbl_hdr;
|
||||
struct mt7615_sta *msta;
|
||||
bool new_entry = true;
|
||||
int cmd, err;
|
||||
|
||||
msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta;
|
||||
@ -864,7 +855,13 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
if (IS_ERR(sskb))
|
||||
return PTR_ERR(sskb);
|
||||
|
||||
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, true);
|
||||
if (!sta) {
|
||||
if (mvif->sta_added)
|
||||
new_entry = false;
|
||||
else
|
||||
mvif->sta_added = true;
|
||||
}
|
||||
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, new_entry);
|
||||
if (enable && sta)
|
||||
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
@ -1087,7 +1084,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
|
||||
}
|
||||
|
||||
mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
|
||||
wcid, NULL, 0, NULL, true);
|
||||
wcid, NULL, 0, NULL, 0, true);
|
||||
memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
|
||||
req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
|
||||
@ -1518,7 +1515,7 @@ static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)
|
||||
static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
|
||||
{
|
||||
u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;
|
||||
const struct mt7663_fw_trailer *hdr;
|
||||
const struct mt76_connac2_fw_trailer *hdr;
|
||||
const struct mt7663_fw_buf *buf;
|
||||
const struct firmware *fw;
|
||||
const u8 *base_addr;
|
||||
@ -1534,9 +1531,7 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt7663_fw_trailer *)(fw->data + fw->size -
|
||||
FW_V3_COMMON_TAILER_SIZE);
|
||||
|
||||
hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE);
|
||||
dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",
|
||||
hdr->fw_ver, hdr->build_date);
|
||||
dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region);
|
||||
@ -2333,7 +2328,7 @@ int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy)
|
||||
|
||||
.bw = mt7615_mcu_chan_bw(chandef),
|
||||
.band = chandef->center_freq1 > 4000,
|
||||
.dbdc_en = !!dev->mt76.phy2,
|
||||
.dbdc_en = !!dev->mt76.phys[MT_BAND1],
|
||||
};
|
||||
u16 center_freq = chandef->center_freq1;
|
||||
int freq_idx;
|
||||
@ -2454,7 +2449,7 @@ int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)
|
||||
|
||||
.bw = mt7615_mcu_chan_bw(chandef),
|
||||
.band = chandef->center_freq1 > 4000,
|
||||
.dbdc_en = !!dev->mt76.phy2,
|
||||
.dbdc_en = !!dev->mt76.phys[MT_BAND1],
|
||||
};
|
||||
u16 center_freq = chandef->center_freq1;
|
||||
int freq_idx;
|
||||
|
@ -201,9 +201,6 @@ struct mt7615_mcu_rdd_report {
|
||||
} hw_pulse[32];
|
||||
};
|
||||
|
||||
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
|
||||
#define MCU_PKT_ID 0xa0
|
||||
|
||||
enum {
|
||||
MCU_ATE_SET_FREQ_OFFSET = 0xa,
|
||||
MCU_ATE_SET_TX_POWER_CONTROL = 0x15,
|
||||
|
@ -186,14 +186,14 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
/* txwi_size = txd size + txp size */
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common),
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_txp_common),
|
||||
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.token_size = MT7615_TOKEN_SIZE,
|
||||
.tx_prepare_skb = mt7615_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7615_tx_complete_skb,
|
||||
.tx_complete_skb = mt76_connac_tx_complete_skb,
|
||||
.rx_check = mt7615_rx_check,
|
||||
.rx_skb = mt7615_queue_rx_skb,
|
||||
.rx_poll_complete = mt7615_rx_poll_complete,
|
||||
|
@ -141,6 +141,7 @@ struct mt7615_sta {
|
||||
struct mt7615_vif {
|
||||
struct mt76_vif mt76; /* must be first */
|
||||
struct mt7615_sta sta;
|
||||
bool sta_added;
|
||||
};
|
||||
|
||||
struct mib_stats {
|
||||
@ -177,7 +178,6 @@ struct mt7615_phy {
|
||||
|
||||
u8 chfreq;
|
||||
u8 rdd_state;
|
||||
int dfs_state;
|
||||
|
||||
u32 rx_ampdu_ts;
|
||||
u32 ampdu_ref;
|
||||
@ -345,7 +345,7 @@ mt7615_hw_dev(struct ieee80211_hw *hw)
|
||||
static inline struct mt7615_phy *
|
||||
mt7615_ext_phy(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_phy *phy = dev->mt76.phy2;
|
||||
struct mt76_phy *phy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (!phy)
|
||||
return NULL;
|
||||
@ -477,7 +477,8 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev);
|
||||
int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta, int pid,
|
||||
struct ieee80211_key_conf *key, bool beacon);
|
||||
struct ieee80211_key_conf *key,
|
||||
enum mt76_txq_id qid, bool beacon);
|
||||
void mt7615_mac_set_timing(struct mt7615_phy *phy);
|
||||
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
||||
struct mt76_wcid *wcid,
|
||||
@ -507,7 +508,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
struct mt76_tx_info *tx_info);
|
||||
|
||||
void mt7615_tx_worker(struct mt76_worker *w);
|
||||
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
void mt7615_tx_token_put(struct mt7615_dev *dev);
|
||||
bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
@ -518,8 +518,6 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt7615_mac_work(struct work_struct *work);
|
||||
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
|
||||
struct mt76_txwi_cache *txwi);
|
||||
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
|
||||
int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
|
||||
int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
|
||||
|
@ -14,75 +14,6 @@
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
|
||||
{
|
||||
if (!e->txwi) {
|
||||
dev_kfree_skb_any(e->skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* error path */
|
||||
if (e->skb == DMA_DUMMY_DATA) {
|
||||
struct mt76_txwi_cache *t;
|
||||
struct mt7615_dev *dev;
|
||||
struct mt7615_txp_common *txp;
|
||||
u16 token;
|
||||
|
||||
dev = container_of(mdev, struct mt7615_dev, mt76);
|
||||
txp = mt7615_txwi_to_txp(mdev, e->txwi);
|
||||
|
||||
if (is_mt7615(&dev->mt76))
|
||||
token = le16_to_cpu(txp->fw.token);
|
||||
else
|
||||
token = le16_to_cpu(txp->hw.msdu_id[0]) &
|
||||
~MT_MSDU_ID_VALID;
|
||||
|
||||
t = mt76_token_put(mdev, token);
|
||||
e->skb = t ? t->skb : NULL;
|
||||
}
|
||||
|
||||
if (e->skb)
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
|
||||
void *txp_ptr, u32 id)
|
||||
{
|
||||
struct mt7615_hw_txp *txp = txp_ptr;
|
||||
struct mt7615_txp_ptr *ptr = &txp->ptr[0];
|
||||
int i, nbuf = tx_info->nbuf - 1;
|
||||
u32 last_mask;
|
||||
|
||||
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
|
||||
tx_info->nbuf = 1;
|
||||
|
||||
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
|
||||
|
||||
if (is_mt7663(&dev->mt76))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_AMSDU_LAST |
|
||||
MT_TXD_LEN_MSDU_LAST;
|
||||
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK;
|
||||
u32 addr = tx_info->buf[i + 1].addr;
|
||||
|
||||
if (i == nbuf - 1)
|
||||
len |= last_mask;
|
||||
|
||||
if (i & 1) {
|
||||
ptr->buf1 = cpu_to_le32(addr);
|
||||
ptr->len1 = cpu_to_le16(len);
|
||||
ptr++;
|
||||
} else {
|
||||
ptr->buf0 = cpu_to_le32(addr);
|
||||
ptr->len0 = cpu_to_le16(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
|
||||
void *txp_ptr, u32 id)
|
||||
@ -91,7 +22,8 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt7615_fw_txp *txp = txp_ptr;
|
||||
struct mt76_connac_fw_txp *txp = txp_ptr;
|
||||
u8 *rept_wds_wcid = (u8 *)&txp->rept_wds_wcid;
|
||||
int nbuf = tx_info->nbuf - 1;
|
||||
int i;
|
||||
|
||||
@ -122,7 +54,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
|
||||
}
|
||||
|
||||
txp->token = cpu_to_le16(id);
|
||||
txp->rept_wds_wcid = 0xff;
|
||||
*rept_wds_wcid = 0xff;
|
||||
}
|
||||
|
||||
int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
@ -145,9 +77,10 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
|
||||
struct mt7615_phy *phy = &dev->phy;
|
||||
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
|
||||
|
||||
if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2)
|
||||
phy = mdev->phy2->priv;
|
||||
if (phy_idx && mdev->phys[MT_BAND1])
|
||||
phy = mdev->phys[MT_BAND1]->priv;
|
||||
|
||||
spin_lock_bh(&dev->mt76.lock);
|
||||
mt7615_mac_set_rates(phy, msta, &info->control.rates[0],
|
||||
@ -164,14 +97,14 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
||||
mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
|
||||
pid, key, false);
|
||||
pid, key, qid, false);
|
||||
|
||||
txp = txwi + MT_TXD_SIZE;
|
||||
memset(txp, 0, sizeof(struct mt7615_txp_common));
|
||||
memset(txp, 0, sizeof(struct mt76_connac_txp_common));
|
||||
if (is_mt7615(&dev->mt76))
|
||||
mt7615_write_fw_txp(dev, tx_info, txp, id);
|
||||
else
|
||||
mt7615_write_hw_txp(dev, tx_info, txp, id);
|
||||
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
|
||||
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
|
||||
@ -250,16 +183,18 @@ mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
static void
|
||||
mt7615_update_beacons(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_update_vif_beacon, dev->mt76.hw);
|
||||
|
||||
if (!dev->mt76.phy2)
|
||||
if (!mphy_ext)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
|
||||
ieee80211_iterate_active_interfaces(mphy_ext->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_update_vif_beacon, dev->mt76.phy2->hw);
|
||||
mt7615_update_vif_beacon, mphy_ext->hw);
|
||||
}
|
||||
|
||||
void mt7615_mac_reset_work(struct work_struct *work)
|
||||
@ -268,9 +203,10 @@ void mt7615_mac_reset_work(struct work_struct *work)
|
||||
struct mt76_phy *ext_phy;
|
||||
struct mt7615_dev *dev;
|
||||
unsigned long timeout;
|
||||
int i;
|
||||
|
||||
dev = container_of(work, struct mt7615_dev, reset_work);
|
||||
ext_phy = dev->mt76.phy2;
|
||||
ext_phy = dev->mt76.phys[MT_BAND1];
|
||||
phy2 = ext_phy ? ext_phy->priv : NULL;
|
||||
|
||||
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
|
||||
@ -299,8 +235,8 @@ void mt7615_mac_reset_work(struct work_struct *work)
|
||||
mt76_txq_schedule_all(ext_phy);
|
||||
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
napi_disable(&dev->mt76.napi[0]);
|
||||
napi_disable(&dev->mt76.napi[1]);
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
@ -330,11 +266,10 @@ void mt7615_mac_reset_work(struct work_struct *work)
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
|
||||
napi_enable(&dev->mt76.napi[0]);
|
||||
napi_schedule(&dev->mt76.napi[0]);
|
||||
|
||||
napi_enable(&dev->mt76.napi[1]);
|
||||
napi_schedule(&dev->mt76.napi[1]);
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
napi_enable(&dev->mt76.napi[i]);
|
||||
napi_schedule(&dev->mt76.napi[i]);
|
||||
}
|
||||
local_bh_enable();
|
||||
|
||||
ieee80211_wake_queues(mt76_hw(dev));
|
||||
|
@ -49,7 +49,7 @@ mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
__le32 *txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE);
|
||||
|
||||
memset(txwi, 0, MT_USB_TXD_SIZE);
|
||||
mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, false);
|
||||
mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, qid, false);
|
||||
skb_push(skb, MT_USB_TXD_SIZE);
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,28 @@
|
||||
#define MT76_CONNAC_MAX_SCHED_SCAN_SSID 10
|
||||
#define MT76_CONNAC_MAX_SCAN_MATCH 16
|
||||
|
||||
#define MT76_CONNAC_MAX_WMM_SETS 4
|
||||
|
||||
#define MT76_CONNAC_COREDUMP_TIMEOUT (HZ / 20)
|
||||
#define MT76_CONNAC_COREDUMP_SZ (1300 * 1024)
|
||||
|
||||
#define MT_TXD_SIZE (8 * 4)
|
||||
|
||||
#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
|
||||
#define MT_USB_HDR_SIZE 4
|
||||
#define MT_USB_TAIL_SIZE 4
|
||||
|
||||
#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
|
||||
#define MT_SDIO_TAIL_SIZE 8
|
||||
#define MT_SDIO_HDR_SIZE 4
|
||||
|
||||
#define MT_MSDU_ID_VALID BIT(15)
|
||||
|
||||
#define MT_TXD_LEN_LAST BIT(15)
|
||||
#define MT_TXD_LEN_MASK GENMASK(11, 0)
|
||||
#define MT_TXD_LEN_MSDU_LAST BIT(14)
|
||||
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
|
||||
|
||||
enum {
|
||||
CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20,
|
||||
CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40,
|
||||
@ -90,6 +109,46 @@ struct mt76_connac_sta_key_conf {
|
||||
u8 key[16];
|
||||
};
|
||||
|
||||
#define MT_TXP_MAX_BUF_NUM 6
|
||||
|
||||
struct mt76_connac_fw_txp {
|
||||
__le16 flags;
|
||||
__le16 token;
|
||||
u8 bss_idx;
|
||||
__le16 rept_wds_wcid;
|
||||
u8 nbuf;
|
||||
__le32 buf[MT_TXP_MAX_BUF_NUM];
|
||||
__le16 len[MT_TXP_MAX_BUF_NUM];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define MT_HW_TXP_MAX_MSDU_NUM 4
|
||||
#define MT_HW_TXP_MAX_BUF_NUM 4
|
||||
|
||||
struct mt76_connac_txp_ptr {
|
||||
__le32 buf0;
|
||||
__le16 len0;
|
||||
__le16 len1;
|
||||
__le32 buf1;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt76_connac_hw_txp {
|
||||
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
|
||||
struct mt76_connac_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt76_connac_txp_common {
|
||||
union {
|
||||
struct mt76_connac_fw_txp fw;
|
||||
struct mt76_connac_hw_txp hw;
|
||||
};
|
||||
};
|
||||
|
||||
struct mt76_connac_tx_free {
|
||||
__le16 rx_byte_cnt;
|
||||
__le16 ctrl;
|
||||
__le32 txd;
|
||||
} __packed __aligned(4);
|
||||
|
||||
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
|
||||
|
||||
static inline bool is_mt7922(struct mt76_dev *dev)
|
||||
@ -145,6 +204,19 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
|
||||
return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
|
||||
}
|
||||
|
||||
static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(dev)) {
|
||||
case 0x7961:
|
||||
case 0x7922:
|
||||
case 0x7663:
|
||||
case 0x7622:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static inline u8 mt76_connac_chan_bw(struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
static const u8 width_to_bw[] = {
|
||||
@ -170,12 +242,31 @@ static inline u8 mt76_connac_lmac_mapping(u8 ac)
|
||||
return 3 - ac;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
mt76_connac_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
u8 *txwi;
|
||||
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
txwi = mt76_get_txwi_ptr(dev, t);
|
||||
|
||||
return (void *)(txwi + MT_TXD_SIZE);
|
||||
}
|
||||
|
||||
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
|
||||
void mt76_connac_power_save_sched(struct mt76_phy *phy,
|
||||
struct mt76_connac_pm *pm);
|
||||
void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
|
||||
struct mt76_wcid *wcid);
|
||||
|
||||
static inline void mt76_connac_tx_cleanup(struct mt76_dev *dev)
|
||||
{
|
||||
dev->queue_ops->tx_cleanup(dev, dev->q_mcu[MT_MCUQ_WM], false);
|
||||
dev->queue_ops->tx_cleanup(dev, dev->q_mcu[MT_MCUQ_WA], false);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt76_connac_pm_ref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
|
||||
{
|
||||
@ -238,11 +329,36 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
|
||||
mutex_unlock(&dev->mutex);
|
||||
}
|
||||
|
||||
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
||||
int ring_base, u32 flags);
|
||||
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
||||
struct mt76_tx_info *tx_info,
|
||||
void *txp_ptr, u32 id);
|
||||
void mt76_connac_txp_skb_unmap(struct mt76_dev *dev,
|
||||
struct mt76_txwi_cache *txwi);
|
||||
void mt76_connac_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e);
|
||||
void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
|
||||
struct mt76_connac_pm *pm,
|
||||
struct mt76_wcid *wcid,
|
||||
struct sk_buff *skb);
|
||||
void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
|
||||
struct mt76_connac_pm *pm);
|
||||
void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
int pid, __le32 *txs_data,
|
||||
struct mt76_sta_stats *stats);
|
||||
void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
|
||||
struct sk_buff *skb,
|
||||
__le32 *rxv, u32 mode);
|
||||
int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb, u16 hdr_offset);
|
||||
int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
|
||||
struct mt76_rx_status *status,
|
||||
struct ieee80211_supported_band *sband,
|
||||
__le32 *rxv, u8 *mode);
|
||||
|
||||
#endif /* __MT76_CONNAC_H */
|
||||
|
323
drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
Normal file
323
drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
Normal file
@ -0,0 +1,323 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2022 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT76_CONNAC2_MAC_H
|
||||
#define __MT76_CONNAC2_MAC_H
|
||||
|
||||
enum tx_header_format {
|
||||
MT_HDR_FORMAT_802_3,
|
||||
MT_HDR_FORMAT_CMD,
|
||||
MT_HDR_FORMAT_802_11,
|
||||
MT_HDR_FORMAT_802_11_EXT,
|
||||
};
|
||||
|
||||
enum tx_pkt_type {
|
||||
MT_TX_TYPE_CT,
|
||||
MT_TX_TYPE_SF,
|
||||
MT_TX_TYPE_CMD,
|
||||
MT_TX_TYPE_FW,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_CTX0,
|
||||
MT_HIF0 = 0x0,
|
||||
|
||||
MT_LMAC_AC00 = 0x0,
|
||||
MT_LMAC_AC01,
|
||||
MT_LMAC_AC02,
|
||||
MT_LMAC_AC03,
|
||||
MT_LMAC_ALTX0 = 0x10,
|
||||
MT_LMAC_BMC0,
|
||||
MT_LMAC_BCN0,
|
||||
MT_LMAC_PSMP0,
|
||||
};
|
||||
|
||||
#define MT_TXD0_Q_IDX GENMASK(31, 25)
|
||||
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
|
||||
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
|
||||
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
|
||||
|
||||
#define MT_TXD1_LONG_FORMAT BIT(31)
|
||||
#define MT_TXD1_TGID BIT(30)
|
||||
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
|
||||
#define MT_TXD1_AMSDU BIT(23)
|
||||
#define MT_TXD1_TID GENMASK(22, 20)
|
||||
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
|
||||
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
|
||||
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
|
||||
#define MT_TXD1_ETH_802_3 BIT(15)
|
||||
#define MT_TXD1_VTA BIT(10)
|
||||
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
|
||||
|
||||
#define MT_TXD2_FIX_RATE BIT(31)
|
||||
#define MT_TXD2_FIXED_RATE BIT(30)
|
||||
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
|
||||
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
|
||||
#define MT_TXD2_FRAG GENMASK(15, 14)
|
||||
#define MT_TXD2_HTC_VLD BIT(13)
|
||||
#define MT_TXD2_DURATION BIT(12)
|
||||
#define MT_TXD2_BIP BIT(11)
|
||||
#define MT_TXD2_MULTICAST BIT(10)
|
||||
#define MT_TXD2_RTS BIT(9)
|
||||
#define MT_TXD2_SOUNDING BIT(8)
|
||||
#define MT_TXD2_NDPA BIT(7)
|
||||
#define MT_TXD2_NDP BIT(6)
|
||||
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
|
||||
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
|
||||
|
||||
#define MT_TXD3_SN_VALID BIT(31)
|
||||
#define MT_TXD3_PN_VALID BIT(30)
|
||||
#define MT_TXD3_SW_POWER_MGMT BIT(29)
|
||||
#define MT_TXD3_BA_DISABLE BIT(28)
|
||||
#define MT_TXD3_SEQ GENMASK(27, 16)
|
||||
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
|
||||
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
|
||||
#define MT_TXD3_TIMING_MEASURE BIT(5)
|
||||
#define MT_TXD3_DAS BIT(4)
|
||||
#define MT_TXD3_EEOSP BIT(3)
|
||||
#define MT_TXD3_EMRD BIT(2)
|
||||
#define MT_TXD3_PROTECT_FRAME BIT(1)
|
||||
#define MT_TXD3_NO_ACK BIT(0)
|
||||
|
||||
#define MT_TXD4_PN_LOW GENMASK(31, 0)
|
||||
|
||||
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
|
||||
#define MT_TXD5_MD BIT(15)
|
||||
#define MT_TXD5_ADD_BA BIT(14)
|
||||
#define MT_TXD5_TX_STATUS_HOST BIT(10)
|
||||
#define MT_TXD5_TX_STATUS_MCU BIT(9)
|
||||
#define MT_TXD5_TX_STATUS_FMT BIT(8)
|
||||
#define MT_TXD5_PID GENMASK(7, 0)
|
||||
|
||||
#define MT_TXD6_TX_IBF BIT(31)
|
||||
#define MT_TXD6_TX_EBF BIT(30)
|
||||
#define MT_TXD6_TX_RATE GENMASK(29, 16)
|
||||
#define MT_TXD6_SGI GENMASK(15, 14)
|
||||
#define MT_TXD6_HELTF GENMASK(13, 12)
|
||||
#define MT_TXD6_LDPC BIT(11)
|
||||
#define MT_TXD6_SPE_ID_IDX BIT(10)
|
||||
#define MT_TXD6_ANT_ID GENMASK(7, 4)
|
||||
#define MT_TXD6_DYN_BW BIT(3)
|
||||
#define MT_TXD6_FIXED_BW BIT(2)
|
||||
#define MT_TXD6_BW GENMASK(1, 0)
|
||||
|
||||
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
|
||||
#define MT_TXD7_UDP_TCP_SUM BIT(29)
|
||||
#define MT_TXD7_IP_SUM BIT(28)
|
||||
#define MT_TXD7_TYPE GENMASK(21, 20)
|
||||
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
|
||||
|
||||
#define MT_TXD7_PSE_FID GENMASK(27, 16)
|
||||
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
|
||||
#define MT_TXD7_HW_AMSDU BIT(10)
|
||||
#define MT_TXD7_TX_TIME GENMASK(9, 0)
|
||||
|
||||
#define MT_TXD8_L_TYPE GENMASK(5, 4)
|
||||
#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0)
|
||||
|
||||
#define MT_TX_RATE_STBC BIT(13)
|
||||
#define MT_TX_RATE_NSS GENMASK(12, 10)
|
||||
#define MT_TX_RATE_MODE GENMASK(9, 6)
|
||||
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
|
||||
#define MT_TX_RATE_DCM BIT(4)
|
||||
/* VHT/HE only use bits 0-3 */
|
||||
#define MT_TX_RATE_IDX GENMASK(5, 0)
|
||||
|
||||
#define MT_TXS0_FIXED_RATE BIT(31)
|
||||
#define MT_TXS0_BW GENMASK(30, 29)
|
||||
#define MT_TXS0_TID GENMASK(28, 26)
|
||||
#define MT_TXS0_AMPDU BIT(25)
|
||||
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
|
||||
#define MT_TXS0_BA_ERROR BIT(22)
|
||||
#define MT_TXS0_PS_FLAG BIT(21)
|
||||
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
|
||||
#define MT_TXS0_BIP_ERROR BIT(19)
|
||||
|
||||
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
|
||||
#define MT_TXS0_RTS_TIMEOUT BIT(17)
|
||||
#define MT_TXS0_ACK_TIMEOUT BIT(16)
|
||||
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
|
||||
|
||||
#define MT_TXS0_TX_STATUS_HOST BIT(15)
|
||||
#define MT_TXS0_TX_STATUS_MCU BIT(14)
|
||||
#define MT_TXS0_TX_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXS1_SEQNO GENMASK(31, 20)
|
||||
#define MT_TXS1_RESP_RATE GENMASK(19, 16)
|
||||
#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
|
||||
#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
|
||||
|
||||
#define MT_TXS2_BF_STATUS GENMASK(31, 30)
|
||||
#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27)
|
||||
#define MT_TXS2_SHARED_ANTENNA BIT(26)
|
||||
#define MT_TXS2_WCID GENMASK(25, 16)
|
||||
#define MT_TXS2_TX_DELAY GENMASK(15, 0)
|
||||
|
||||
#define MT_TXS3_PID GENMASK(31, 24)
|
||||
#define MT_TXS3_ANT_ID GENMASK(23, 0)
|
||||
|
||||
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
|
||||
|
||||
/* RXD DW1 */
|
||||
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
|
||||
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
|
||||
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
|
||||
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
|
||||
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
|
||||
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
|
||||
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
|
||||
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
|
||||
#define MT_RXD1_NORMAL_CM BIT(23)
|
||||
#define MT_RXD1_NORMAL_CLM BIT(24)
|
||||
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
|
||||
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
|
||||
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
|
||||
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
|
||||
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
|
||||
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
|
||||
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
|
||||
|
||||
/* RXD DW2 */
|
||||
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
|
||||
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
|
||||
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
|
||||
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
|
||||
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
|
||||
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
|
||||
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
|
||||
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
|
||||
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
|
||||
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
|
||||
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
|
||||
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
|
||||
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
|
||||
#define MT_RXD2_NORMAL_FRAG BIT(27)
|
||||
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
|
||||
#define MT_RXD2_NORMAL_NDATA BIT(29)
|
||||
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
|
||||
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
|
||||
|
||||
/* RXD DW4 */
|
||||
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
|
||||
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
|
||||
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
|
||||
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
|
||||
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
|
||||
#define MT_RXD4_NORMAL_CLS BIT(10)
|
||||
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
|
||||
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
|
||||
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
|
||||
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
|
||||
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
|
||||
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
|
||||
|
||||
#define MT_RXV_HDR_BAND_IDX BIT(24)
|
||||
|
||||
/* RXD DW3 */
|
||||
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
|
||||
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
|
||||
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
|
||||
#define MT_RXD3_NORMAL_U2M BIT(0)
|
||||
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
|
||||
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
|
||||
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
|
||||
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
|
||||
#define MT_RXD3_NORMAL_AMSDU BIT(22)
|
||||
#define MT_RXD3_NORMAL_MESH BIT(23)
|
||||
#define MT_RXD3_NORMAL_MHCP BIT(24)
|
||||
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
|
||||
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
|
||||
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
|
||||
#define MT_RXD3_NORMAL_MORE BIT(28)
|
||||
#define MT_RXD3_NORMAL_UNWANT BIT(29)
|
||||
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
|
||||
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
|
||||
|
||||
/* RXD GROUP4 */
|
||||
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
|
||||
#define MT_RXD6_TA_LO GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD7_TA_HI GENMASK(31, 0)
|
||||
|
||||
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
|
||||
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
|
||||
|
||||
/* P-RXV DW0 */
|
||||
#define MT_PRXV_TX_RATE GENMASK(6, 0)
|
||||
#define MT_PRXV_TX_DCM BIT(4)
|
||||
#define MT_PRXV_TX_ER_SU_106T BIT(5)
|
||||
#define MT_PRXV_NSTS GENMASK(9, 7)
|
||||
#define MT_PRXV_TXBF BIT(10)
|
||||
#define MT_PRXV_HT_AD_CODE BIT(11)
|
||||
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
|
||||
|
||||
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
|
||||
#define MT_PRXV_HT_SGI GENMASK(16, 15)
|
||||
#define MT_PRXV_HT_STBC GENMASK(23, 22)
|
||||
#define MT_PRXV_TX_MODE GENMASK(27, 24)
|
||||
#define MT_PRXV_DCM BIT(17)
|
||||
#define MT_PRXV_NUM_RX BIT(20, 18)
|
||||
|
||||
/* P-RXV DW1 */
|
||||
#define MT_PRXV_RCPI3 GENMASK(31, 24)
|
||||
#define MT_PRXV_RCPI2 GENMASK(23, 16)
|
||||
#define MT_PRXV_RCPI1 GENMASK(15, 8)
|
||||
#define MT_PRXV_RCPI0 GENMASK(7, 0)
|
||||
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
|
||||
|
||||
/* C-RXV */
|
||||
#define MT_CRXV_HT_STBC GENMASK(1, 0)
|
||||
#define MT_CRXV_TX_MODE GENMASK(7, 4)
|
||||
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
|
||||
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
|
||||
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
|
||||
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
|
||||
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
|
||||
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
|
||||
#define MT_CRXV_HE_UPLINK BIT(31)
|
||||
|
||||
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
|
||||
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
|
||||
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
|
||||
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
|
||||
|
||||
#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
|
||||
|
||||
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
|
||||
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
|
||||
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
|
||||
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
|
||||
|
||||
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
|
||||
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
|
||||
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
|
||||
#define MT_CRXV_HE_DOPPLER BIT(16)
|
||||
|
||||
#define MT_CRXV_SNR GENMASK(18, 13)
|
||||
#define MT_CRXV_FOE_LO GENMASK(31, 19)
|
||||
#define MT_CRXV_FOE_HI GENMASK(6, 0)
|
||||
#define MT_CRXV_FOE_SHIFT 13
|
||||
|
||||
#define MT_CT_INFO_APPLY_TXD BIT(0)
|
||||
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
|
||||
#define MT_CT_INFO_MGMT_FRAME BIT(2)
|
||||
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
|
||||
#define MT_CT_INFO_HSR2_TX BIT(4)
|
||||
#define MT_CT_INFO_FROM_HOST BIT(7)
|
||||
|
||||
enum tx_mcu_port_q_idx {
|
||||
MT_TX_MCU_PORT_RX_Q0 = 0x20,
|
||||
MT_TX_MCU_PORT_RX_Q1,
|
||||
MT_TX_MCU_PORT_RX_Q2,
|
||||
MT_TX_MCU_PORT_RX_Q3,
|
||||
MT_TX_MCU_PORT_RX_FWDL = 0x3e
|
||||
};
|
||||
|
||||
enum tx_port_idx {
|
||||
MT_TX_PORT_IDX_LMAC,
|
||||
MT_TX_PORT_IDX_MCU
|
||||
};
|
||||
|
||||
#endif /* __MT76_CONNAC2_MAC_H */
|
@ -2,6 +2,12 @@
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include "mt76_connac.h"
|
||||
#include "mt76_connac2_mac.h"
|
||||
#include "dma.h"
|
||||
|
||||
#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
|
||||
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
|
||||
IEEE80211_RADIOTAP_HE_##f)
|
||||
|
||||
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
|
||||
{
|
||||
@ -115,3 +121,917 @@ void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
|
||||
mt76_worker_schedule(&phy->dev->tx_worker);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_pm_dequeue_skbs);
|
||||
|
||||
void mt76_connac_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e)
|
||||
{
|
||||
if (!e->txwi) {
|
||||
dev_kfree_skb_any(e->skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* error path */
|
||||
if (e->skb == DMA_DUMMY_DATA) {
|
||||
struct mt76_connac_txp_common *txp;
|
||||
struct mt76_txwi_cache *t;
|
||||
u16 token;
|
||||
|
||||
txp = mt76_connac_txwi_to_txp(mdev, e->txwi);
|
||||
if (is_mt76_fw_txp(mdev))
|
||||
token = le16_to_cpu(txp->fw.token);
|
||||
else
|
||||
token = le16_to_cpu(txp->hw.msdu_id[0]) &
|
||||
~MT_MSDU_ID_VALID;
|
||||
|
||||
t = mt76_token_put(mdev, token);
|
||||
e->skb = t ? t->skb : NULL;
|
||||
}
|
||||
|
||||
if (e->skb)
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_tx_complete_skb);
|
||||
|
||||
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
||||
struct mt76_tx_info *tx_info,
|
||||
void *txp_ptr, u32 id)
|
||||
{
|
||||
struct mt76_connac_hw_txp *txp = txp_ptr;
|
||||
struct mt76_connac_txp_ptr *ptr = &txp->ptr[0];
|
||||
int i, nbuf = tx_info->nbuf - 1;
|
||||
u32 last_mask;
|
||||
|
||||
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
|
||||
tx_info->nbuf = 1;
|
||||
|
||||
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
|
||||
|
||||
if (is_mt7663(dev) || is_mt7921(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_AMSDU_LAST |
|
||||
MT_TXD_LEN_MSDU_LAST;
|
||||
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK;
|
||||
u32 addr = tx_info->buf[i + 1].addr;
|
||||
|
||||
if (i == nbuf - 1)
|
||||
len |= last_mask;
|
||||
|
||||
if (i & 1) {
|
||||
ptr->buf1 = cpu_to_le32(addr);
|
||||
ptr->len1 = cpu_to_le16(len);
|
||||
ptr++;
|
||||
} else {
|
||||
ptr->buf0 = cpu_to_le32(addr);
|
||||
ptr->len0 = cpu_to_le16(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_write_hw_txp);
|
||||
|
||||
static void
|
||||
mt76_connac_txp_skb_unmap_fw(struct mt76_dev *mdev,
|
||||
struct mt76_connac_fw_txp *txp)
|
||||
{
|
||||
struct device *dev = is_connac_v1(mdev) ? mdev->dev : mdev->dma_dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < txp->nbuf; i++)
|
||||
dma_unmap_single(dev, le32_to_cpu(txp->buf[i]),
|
||||
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev,
|
||||
struct mt76_connac_hw_txp *txp)
|
||||
{
|
||||
u32 last_mask;
|
||||
int i;
|
||||
|
||||
if (is_mt7663(dev) || is_mt7921(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_MSDU_LAST;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) {
|
||||
struct mt76_connac_txp_ptr *ptr = &txp->ptr[i];
|
||||
bool last;
|
||||
u16 len;
|
||||
|
||||
len = le16_to_cpu(ptr->len0);
|
||||
last = len & last_mask;
|
||||
len &= MT_TXD_LEN_MASK;
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len,
|
||||
DMA_TO_DEVICE);
|
||||
if (last)
|
||||
break;
|
||||
|
||||
len = le16_to_cpu(ptr->len1);
|
||||
last = len & last_mask;
|
||||
len &= MT_TXD_LEN_MASK;
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len,
|
||||
DMA_TO_DEVICE);
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_connac_txp_skb_unmap(struct mt76_dev *dev,
|
||||
struct mt76_txwi_cache *t)
|
||||
{
|
||||
struct mt76_connac_txp_common *txp;
|
||||
|
||||
txp = mt76_connac_txwi_to_txp(dev, t);
|
||||
if (is_mt76_fw_txp(dev))
|
||||
mt76_connac_txp_skb_unmap_fw(dev, &txp->fw);
|
||||
else
|
||||
mt76_connac_txp_skb_unmap_hw(dev, &txp->hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap);
|
||||
|
||||
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
||||
int ring_base, u32 flags)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, flags);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 1; i <= MT_TXQ_PSD; i++)
|
||||
phy->q_tx[i] = phy->q_tx[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues);
|
||||
|
||||
static u16
|
||||
mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast)
|
||||
{
|
||||
u8 mode = 0, band = mphy->chandef.chan->band;
|
||||
int rateidx = 0, mcast_rate;
|
||||
|
||||
if (!vif)
|
||||
goto legacy;
|
||||
|
||||
if (is_mt7921(mphy->dev)) {
|
||||
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
goto legacy;
|
||||
}
|
||||
|
||||
if (beacon) {
|
||||
struct cfg80211_bitrate_mask *mask;
|
||||
|
||||
mask = &vif->bss_conf.beacon_tx_rate;
|
||||
if (hweight16(mask->control[band].he_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].he_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_HE_SU;
|
||||
goto out;
|
||||
} else if (hweight16(mask->control[band].vht_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].vht_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_VHT;
|
||||
goto out;
|
||||
} else if (hweight8(mask->control[band].ht_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].ht_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_HT;
|
||||
goto out;
|
||||
} else if (hweight32(mask->control[band].legacy) == 1) {
|
||||
rateidx = ffs(mask->control[band].legacy) - 1;
|
||||
goto legacy;
|
||||
}
|
||||
}
|
||||
|
||||
mcast_rate = vif->bss_conf.mcast_rate[band];
|
||||
if (mcast && mcast_rate > 0)
|
||||
rateidx = mcast_rate - 1;
|
||||
else
|
||||
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
|
||||
legacy:
|
||||
rateidx = mt76_calculate_default_rate(mphy, rateidx);
|
||||
mode = rateidx >> 8;
|
||||
rateidx &= GENMASK(7, 0);
|
||||
|
||||
out:
|
||||
return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
|
||||
FIELD_PREP(MT_TX_RATE_MODE, mode);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_connac2_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid)
|
||||
{
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u8 fc_type, fc_stype;
|
||||
u16 ethertype;
|
||||
bool wmm = false;
|
||||
u32 val;
|
||||
|
||||
if (wcid->sta) {
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
||||
wmm = sta->wme;
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
|
||||
FIELD_PREP(MT_TXD1_TID, tid);
|
||||
|
||||
ethertype = get_unaligned_be16(&skb->data[12]);
|
||||
if (ethertype >= ETH_P_802_3_MIN)
|
||||
val |= MT_TXD1_ETH_802_3;
|
||||
|
||||
txwi[1] |= cpu_to_le32(val);
|
||||
|
||||
fc_type = IEEE80211_FTYPE_DATA >> 2;
|
||||
fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
|
||||
|
||||
txwi[2] |= cpu_to_le32(val);
|
||||
|
||||
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
||||
|
||||
txwi[7] |= cpu_to_le32(val);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 fc_type, fc_stype;
|
||||
u32 val;
|
||||
|
||||
if (ieee80211_is_action(fc) &&
|
||||
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
|
||||
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
|
||||
u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
|
||||
|
||||
txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA);
|
||||
tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
} else if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr;
|
||||
u16 control = le16_to_cpu(bar->control);
|
||||
|
||||
tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control);
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
|
||||
FIELD_PREP(MT_TXD1_HDR_INFO,
|
||||
ieee80211_get_hdrlen_from_skb(skb) / 2) |
|
||||
FIELD_PREP(MT_TXD1_TID, tid);
|
||||
|
||||
txwi[1] |= cpu_to_le32(val);
|
||||
|
||||
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
|
||||
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
|
||||
|
||||
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |
|
||||
FIELD_PREP(MT_TXD2_MULTICAST, multicast);
|
||||
|
||||
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
|
||||
key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
|
||||
val |= MT_TXD2_BIP;
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
|
||||
}
|
||||
|
||||
if (!ieee80211_is_data(fc) || multicast ||
|
||||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
|
||||
val |= MT_TXD2_FIX_RATE;
|
||||
|
||||
txwi[2] |= cpu_to_le32(val);
|
||||
|
||||
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);
|
||||
if (!is_mt7921(dev))
|
||||
txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
|
||||
0x18));
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
||||
u16 seqno = le16_to_cpu(hdr->seq_ctrl);
|
||||
|
||||
if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
struct ieee80211_bar *bar;
|
||||
|
||||
bar = (struct ieee80211_bar *)skb->data;
|
||||
seqno = le16_to_cpu(bar->start_seq_num);
|
||||
}
|
||||
|
||||
val = MT_TXD3_SN_VALID |
|
||||
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
|
||||
txwi[3] |= cpu_to_le32(val);
|
||||
txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
|
||||
}
|
||||
|
||||
if (mt76_is_mmio(dev)) {
|
||||
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
||||
txwi[7] |= cpu_to_le32(val);
|
||||
} else {
|
||||
val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
|
||||
txwi[8] |= cpu_to_le32(val);
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt76_phy *mphy = &dev->phy;
|
||||
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0;
|
||||
u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED));
|
||||
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
BSS_CHANGED_FILS_DISCOVERY));
|
||||
|
||||
if (vif) {
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
|
||||
omac_idx = mvif->omac_idx;
|
||||
wmm_idx = mvif->wmm_idx;
|
||||
band_idx = mvif->band_idx;
|
||||
}
|
||||
|
||||
if (phy_idx && dev->phys[MT_BAND1])
|
||||
mphy = dev->phys[MT_BAND1];
|
||||
|
||||
if (inband_disc) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_ALTX0;
|
||||
} else if (beacon) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_BCN0;
|
||||
} else if (qid >= MT_TXQ_PSD) {
|
||||
p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
|
||||
q_idx = MT_LMAC_ALTX0;
|
||||
} else {
|
||||
p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
|
||||
q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
|
||||
mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
|
||||
FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
|
||||
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
|
||||
txwi[0] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
||||
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
||||
if (!is_mt7921(dev))
|
||||
val |= MT_TXD1_VTA;
|
||||
if (phy_idx || band_idx)
|
||||
val |= MT_TXD1_TGID;
|
||||
|
||||
txwi[1] = cpu_to_le32(val);
|
||||
txwi[2] = 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);
|
||||
if (!is_mt7921(dev))
|
||||
val |= MT_TXD3_SW_POWER_MGMT;
|
||||
if (key)
|
||||
val |= MT_TXD3_PROTECT_FRAME;
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
val |= MT_TXD3_NO_ACK;
|
||||
|
||||
txwi[3] = cpu_to_le32(val);
|
||||
txwi[4] = 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD5_PID, pid);
|
||||
if (pid >= MT_PACKET_ID_FIRST)
|
||||
val |= MT_TXD5_TX_STATUS_HOST;
|
||||
|
||||
txwi[5] = cpu_to_le32(val);
|
||||
txwi[6] = 0;
|
||||
txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
|
||||
|
||||
if (is_8023)
|
||||
mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid);
|
||||
else
|
||||
mt76_connac2_mac_write_txwi_80211(dev, txwi, skb, key);
|
||||
|
||||
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
|
||||
/* Fixed rata is available just for 802.11 txd */
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
|
||||
multicast);
|
||||
u32 val = MT_TXD6_FIXED_BW;
|
||||
|
||||
/* hardware won't add HTC for mgmt/ctrl frame */
|
||||
txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
|
||||
|
||||
val |= FIELD_PREP(MT_TXD6_TX_RATE, rate);
|
||||
txwi[6] |= cpu_to_le32(val);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi);
|
||||
|
||||
bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
int pid, __le32 *txs_data,
|
||||
struct mt76_sta_stats *stats)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt76_phy *mphy;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff_head list;
|
||||
struct rate_info rate = {};
|
||||
struct sk_buff *skb;
|
||||
bool cck = false;
|
||||
u32 txrate, txs, mode;
|
||||
|
||||
mt76_tx_status_lock(dev, &list);
|
||||
skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
info->status.ampdu_len = 1;
|
||||
info->status.ampdu_ack_len = !!(info->flags &
|
||||
IEEE80211_TX_STAT_ACK);
|
||||
|
||||
info->status.rates[0].idx = -1;
|
||||
|
||||
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
|
||||
|
||||
rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
|
||||
rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
|
||||
|
||||
if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
|
||||
stats->tx_nss[rate.nss - 1]++;
|
||||
if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
|
||||
stats->tx_mcs[rate.mcs]++;
|
||||
|
||||
mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
|
||||
switch (mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
mphy = &dev->phy;
|
||||
if (wcid->phy_idx == MT_BAND1 && dev->phys[MT_BAND1])
|
||||
mphy = dev->phys[MT_BAND1];
|
||||
|
||||
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;
|
||||
|
||||
rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
|
||||
rate.legacy = sband->bitrates[rate.mcs].bitrate;
|
||||
break;
|
||||
case MT_PHY_TYPE_HT:
|
||||
case MT_PHY_TYPE_HT_GF:
|
||||
if (rate.mcs > 31)
|
||||
goto out;
|
||||
|
||||
rate.flags = RATE_INFO_FLAGS_MCS;
|
||||
if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
|
||||
rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
if (rate.mcs > 9)
|
||||
goto out;
|
||||
|
||||
rate.flags = RATE_INFO_FLAGS_VHT_MCS;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
if (rate.mcs > 11)
|
||||
goto out;
|
||||
|
||||
rate.he_gi = wcid->rate.he_gi;
|
||||
rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
|
||||
rate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
stats->tx_mode[mode]++;
|
||||
|
||||
switch (FIELD_GET(MT_TXS0_BW, txs)) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
rate.bw = RATE_INFO_BW_160;
|
||||
stats->tx_bw[3]++;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
rate.bw = RATE_INFO_BW_80;
|
||||
stats->tx_bw[2]++;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
rate.bw = RATE_INFO_BW_40;
|
||||
stats->tx_bw[1]++;
|
||||
break;
|
||||
default:
|
||||
rate.bw = RATE_INFO_BW_20;
|
||||
stats->tx_bw[0]++;
|
||||
break;
|
||||
}
|
||||
wcid->rate = rate;
|
||||
|
||||
out:
|
||||
if (skb)
|
||||
mt76_tx_status_skb_done(dev, skb, &list);
|
||||
|
||||
mt76_tx_status_unlock(dev, &list);
|
||||
|
||||
return !!skb;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mac_add_txs_skb);
|
||||
|
||||
static void
|
||||
mt76_connac2_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
||||
struct ieee80211_radiotap_he *he,
|
||||
__le32 *rxv)
|
||||
{
|
||||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
|
||||
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;
|
||||
|
||||
switch (ru) {
|
||||
case 0 ... 36:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
offs = ru;
|
||||
break;
|
||||
case 37 ... 52:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
offs = ru - 37;
|
||||
break;
|
||||
case 53 ... 60:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
offs = ru - 53;
|
||||
break;
|
||||
case 61 ... 64:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
offs = ru - 61;
|
||||
break;
|
||||
case 65 ... 66:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
offs = ru - 65;
|
||||
break;
|
||||
case 67:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
break;
|
||||
case 68:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
|
||||
break;
|
||||
}
|
||||
|
||||
he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
|
||||
le16_encode_bits(offs,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_connac2_mac_decode_he_mu_radiotap(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
__le32 *rxv)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
static struct ieee80211_radiotap_he_mu mu_known = {
|
||||
.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
|
||||
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
|
||||
};
|
||||
struct ieee80211_radiotap_he_mu *he_mu;
|
||||
|
||||
if (is_mt7921(dev)) {
|
||||
mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN);
|
||||
mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN);
|
||||
}
|
||||
|
||||
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
|
||||
|
||||
he_mu = skb_push(skb, sizeof(mu_known));
|
||||
memcpy(he_mu, &mu_known, sizeof(mu_known));
|
||||
|
||||
#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
|
||||
|
||||
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
|
||||
if (status->he_dcm)
|
||||
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
|
||||
|
||||
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
|
||||
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
|
||||
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
|
||||
|
||||
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] =
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
|
||||
}
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_80) {
|
||||
he_mu->ru_ch1[1] =
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
|
||||
he_mu->ru_ch2[1] =
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
|
||||
struct sk_buff *skb,
|
||||
__le32 *rxv, u32 mode)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
static const struct ieee80211_radiotap_he known = {
|
||||
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
|
||||
HE_BITS(DATA1_DATA_DCM_KNOWN) |
|
||||
HE_BITS(DATA1_STBC_KNOWN) |
|
||||
HE_BITS(DATA1_CODING_KNOWN) |
|
||||
HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
|
||||
HE_BITS(DATA1_DOPPLER_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
|
||||
HE_BITS(DATA1_BSS_COLOR_KNOWN),
|
||||
.data2 = HE_BITS(DATA2_GI_KNOWN) |
|
||||
HE_BITS(DATA2_TXBF_KNOWN) |
|
||||
HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
|
||||
HE_BITS(DATA2_TXOP_KNOWN),
|
||||
};
|
||||
u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
|
||||
struct ieee80211_radiotap_he *he;
|
||||
|
||||
status->flag |= RX_FLAG_RADIOTAP_HE;
|
||||
|
||||
he = skb_push(skb, sizeof(known));
|
||||
memcpy(he, &known, sizeof(known));
|
||||
|
||||
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
|
||||
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
|
||||
he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
|
||||
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
|
||||
le16_encode_bits(ltf_size,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
|
||||
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
|
||||
he->data5 |= HE_BITS(DATA5_TXBF);
|
||||
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
|
||||
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
|
||||
|
||||
switch (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_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_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
|
||||
|
||||
mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv);
|
||||
mt76_connac2_mac_decode_he_mu_radiotap(dev, skb, rxv);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
|
||||
HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
|
||||
|
||||
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]);
|
||||
|
||||
mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mac_decode_he_radiotap);
|
||||
|
||||
/* The HW does not translate the mac header to 802.3 for mesh point */
|
||||
int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb, u16 hdr_offset)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_offset);
|
||||
__le32 *rxd = (__le32 *)skb->data;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4))
|
||||
return -EINVAL;
|
||||
|
||||
sta = container_of((void *)status->wcid, struct ieee80211_sta, drv_priv);
|
||||
|
||||
/* store the info from RXD and ethhdr to avoid being overridden */
|
||||
frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL);
|
||||
hdr.frame_control = cpu_to_le16(frame_control);
|
||||
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL));
|
||||
hdr.duration_id = 0;
|
||||
|
||||
ether_addr_copy(hdr.addr1, vif->addr);
|
||||
ether_addr_copy(hdr.addr2, sta->addr);
|
||||
switch (frame_control & (IEEE80211_FCTL_TODS |
|
||||
IEEE80211_FCTL_FROMDS)) {
|
||||
case 0:
|
||||
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
|
||||
break;
|
||||
case IEEE80211_FCTL_FROMDS:
|
||||
ether_addr_copy(hdr.addr3, eth_hdr->h_source);
|
||||
break;
|
||||
case IEEE80211_FCTL_TODS:
|
||||
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
|
||||
break;
|
||||
case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:
|
||||
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
|
||||
ether_addr_copy(hdr.addr4, eth_hdr->h_source);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
skb_pull(skb, hdr_offset + sizeof(struct ethhdr) - 2);
|
||||
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
|
||||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
|
||||
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
|
||||
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
|
||||
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
|
||||
else
|
||||
skb_pull(skb, 2);
|
||||
|
||||
if (ieee80211_has_order(hdr.frame_control))
|
||||
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9],
|
||||
IEEE80211_HT_CTL_LEN);
|
||||
if (ieee80211_is_data_qos(hdr.frame_control)) {
|
||||
__le16 qos_ctrl;
|
||||
|
||||
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL));
|
||||
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
|
||||
IEEE80211_QOS_CTL_LEN);
|
||||
}
|
||||
|
||||
if (ieee80211_has_a4(hdr.frame_control))
|
||||
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
|
||||
else
|
||||
memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_reverse_frag0_hdr_trans);
|
||||
|
||||
int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
|
||||
struct mt76_rx_status *status,
|
||||
struct ieee80211_supported_band *sband,
|
||||
__le32 *rxv, u8 *mode)
|
||||
{
|
||||
u32 v0, v2;
|
||||
u8 stbc, gi, bw, dcm, nss;
|
||||
int i, idx;
|
||||
bool cck = false;
|
||||
|
||||
v0 = le32_to_cpu(rxv[0]);
|
||||
v2 = le32_to_cpu(rxv[2]);
|
||||
|
||||
idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
|
||||
nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
|
||||
|
||||
if (!is_mt7915(dev)) {
|
||||
stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
|
||||
gi = FIELD_GET(MT_PRXV_HT_SGI, v0);
|
||||
*mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
|
||||
if (is_mt7921(dev))
|
||||
dcm = !!(idx & MT_PRXV_TX_DCM);
|
||||
else
|
||||
dcm = FIELD_GET(MT_PRXV_DCM, v0);
|
||||
bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0);
|
||||
} else {
|
||||
stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
|
||||
gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
|
||||
*mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
|
||||
dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM);
|
||||
bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2);
|
||||
}
|
||||
|
||||
switch (*mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
i = mt76_get_rate(dev, sband, i, cck);
|
||||
break;
|
||||
case MT_PHY_TYPE_HT_GF:
|
||||
case MT_PHY_TYPE_HT:
|
||||
status->encoding = RX_ENC_HT;
|
||||
if (gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
if (i > 31)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
status->nss = nss;
|
||||
status->encoding = RX_ENC_VHT;
|
||||
if (gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
if (i > 11)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
status->nss = nss;
|
||||
status->encoding = RX_ENC_HE;
|
||||
i &= GENMASK(3, 0);
|
||||
|
||||
if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
|
||||
status->he_gi = gi;
|
||||
|
||||
status->he_dcm = dcm;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
status->rate_idx = i;
|
||||
|
||||
switch (bw) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
|
||||
(idx & MT_PRXV_TX_ER_SU_106T)) {
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
status->he_ru =
|
||||
NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
} else {
|
||||
status->bw = RATE_INFO_BW_40;
|
||||
}
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
status->bw = RATE_INFO_BW_80;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
status->bw = RATE_INFO_BW_160;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
|
||||
if (*mode < MT_PHY_TYPE_HE_SU && gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate);
|
||||
|
@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include "mt76_connac2_mac.h"
|
||||
#include "mt76_connac_mcu.h"
|
||||
|
||||
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
|
||||
@ -1403,6 +1405,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
|
||||
else
|
||||
conn_type = CONNECTION_INFRA_AP;
|
||||
basic_req.basic.conn_type = cpu_to_le32(conn_type);
|
||||
/* Fully active/deactivate BSS network in AP mode only */
|
||||
basic_req.basic.active = enable;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (vif->p2p)
|
||||
@ -2808,5 +2812,304 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_rdd_cmd);
|
||||
|
||||
static int
|
||||
mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev,
|
||||
const struct mt76_connac2_fw_trailer *hdr,
|
||||
const u8 *data, bool is_wa)
|
||||
{
|
||||
int i, offset = 0, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
|
||||
u32 override = 0, option = 0;
|
||||
|
||||
for (i = 0; i < hdr->n_region; i++) {
|
||||
const struct mt76_connac2_fw_region *region;
|
||||
u32 len, addr, mode;
|
||||
int err;
|
||||
|
||||
region = (const void *)((const u8 *)hdr -
|
||||
(hdr->n_region - i) * sizeof(*region));
|
||||
mode = mt76_connac_mcu_gen_dl_mode(dev, region->feature_set,
|
||||
is_wa);
|
||||
len = le32_to_cpu(region->len);
|
||||
addr = le32_to_cpu(region->addr);
|
||||
|
||||
if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
|
||||
override = addr;
|
||||
|
||||
err = mt76_connac_mcu_init_download(dev, addr, len, mode);
|
||||
if (err) {
|
||||
dev_err(dev->dev, "Download request failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
|
||||
data + offset, len, max_len);
|
||||
if (err) {
|
||||
dev_err(dev->dev, "Failed to send firmware.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
if (override)
|
||||
option |= FW_START_OVERRIDE;
|
||||
if (is_wa)
|
||||
option |= FW_START_WORKING_PDA_CR4;
|
||||
|
||||
return mt76_connac_mcu_start_firmware(dev, override, option);
|
||||
}
|
||||
|
||||
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
|
||||
const char *fw_wa)
|
||||
{
|
||||
const struct mt76_connac2_fw_trailer *hdr;
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, fw_wm, dev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
|
||||
dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
|
||||
hdr->fw_ver, hdr->build_date);
|
||||
|
||||
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to start WM firmware\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
if (!fw_wa)
|
||||
return 0;
|
||||
|
||||
ret = request_firmware(&fw, fw_wa, dev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
|
||||
dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
|
||||
hdr->fw_ver, hdr->build_date);
|
||||
|
||||
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to start WA firmware\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(dev->hw->wiphy->fw_version,
|
||||
sizeof(dev->hw->wiphy->fw_version),
|
||||
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);
|
||||
|
||||
static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
|
||||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
case PATCH_SEC_ENC_TYPE_PLAIN:
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_AES:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_SCRAMBLE:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= DL_CONFIG_ENCRY_MODE_SEL;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "Encryption type not support!\n");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
|
||||
{
|
||||
int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
|
||||
const struct mt76_connac2_patch_hdr *hdr;
|
||||
const struct firmware *fw = NULL;
|
||||
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);
|
||||
switch (sem) {
|
||||
case PATCH_IS_DL:
|
||||
return 0;
|
||||
case PATCH_NOT_DL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "Failed to get patch semaphore\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, fw_name, dev->dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const void *)fw->data;
|
||||
dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
|
||||
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
|
||||
|
||||
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
|
||||
struct mt76_connac2_patch_sec *sec;
|
||||
u32 len, addr, mode;
|
||||
const u8 *dl;
|
||||
u32 sec_info;
|
||||
|
||||
sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));
|
||||
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
|
||||
PATCH_SEC_TYPE_INFO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = be32_to_cpu(sec->info.addr);
|
||||
len = be32_to_cpu(sec->info.len);
|
||||
dl = fw->data + be32_to_cpu(sec->offs);
|
||||
sec_info = be32_to_cpu(sec->info.sec_key_idx);
|
||||
mode = mt76_connac2_get_data_mode(dev, sec_info);
|
||||
|
||||
ret = mt76_connac_mcu_init_download(dev, addr, len, mode);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Download request failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
|
||||
dl, len, max_len);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to send patch\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_start_patch(dev);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "Failed to start patch\n");
|
||||
|
||||
out:
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(dev, false);
|
||||
switch (sem) {
|
||||
case PATCH_REL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ret = -EAGAIN;
|
||||
dev_err(dev->dev, "Failed to release patch semaphore\n");
|
||||
break;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_load_patch);
|
||||
|
||||
int mt76_connac2_mcu_fill_message(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq)
|
||||
{
|
||||
int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
|
||||
struct mt76_connac2_mcu_uni_txd *uni_txd;
|
||||
struct mt76_connac2_mcu_txd *mcu_txd;
|
||||
__le32 *txd;
|
||||
u32 val;
|
||||
u8 seq;
|
||||
|
||||
/* TODO: make dynamic based on msg type */
|
||||
dev->mcu.timeout = 20 * HZ;
|
||||
|
||||
seq = ++dev->mcu.msg_seq & 0xf;
|
||||
if (!seq)
|
||||
seq = ++dev->mcu.msg_seq & 0xf;
|
||||
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
goto exit;
|
||||
|
||||
txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);
|
||||
txd = (__le32 *)skb_push(skb, txd_len);
|
||||
|
||||
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
|
||||
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |
|
||||
FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);
|
||||
txd[0] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);
|
||||
txd[1] = cpu_to_le32(val);
|
||||
|
||||
if (cmd & __MCU_CMD_FIELD_UNI) {
|
||||
uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd;
|
||||
uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));
|
||||
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
|
||||
uni_txd->cid = cpu_to_le16(mcu_cmd);
|
||||
uni_txd->s2d_index = MCU_S2D_H2N;
|
||||
uni_txd->pkt_type = MCU_PKT_ID;
|
||||
uni_txd->seq = seq;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mcu_txd = (struct mt76_connac2_mcu_txd *)txd;
|
||||
mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
|
||||
mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,
|
||||
MT_TX_MCU_PORT_RX_Q0));
|
||||
mcu_txd->pkt_type = MCU_PKT_ID;
|
||||
mcu_txd->seq = seq;
|
||||
mcu_txd->cid = mcu_cmd;
|
||||
mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
|
||||
|
||||
if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {
|
||||
if (cmd & __MCU_CMD_FIELD_QUERY)
|
||||
mcu_txd->set_query = MCU_Q_QUERY;
|
||||
else
|
||||
mcu_txd->set_query = MCU_Q_SET;
|
||||
mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;
|
||||
} else {
|
||||
mcu_txd->set_query = MCU_Q_NA;
|
||||
}
|
||||
|
||||
if (cmd & __MCU_CMD_FIELD_WA)
|
||||
mcu_txd->s2d_index = MCU_S2D_H2C;
|
||||
else
|
||||
mcu_txd->s2d_index = MCU_S2D_H2N;
|
||||
|
||||
exit:
|
||||
if (wait_seq)
|
||||
*wait_seq = seq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -26,6 +26,157 @@
|
||||
#define PATCH_SEC_TYPE_MASK GENMASK(15, 0)
|
||||
#define PATCH_SEC_TYPE_INFO 0x2
|
||||
|
||||
#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24)
|
||||
#define PATCH_SEC_ENC_TYPE_PLAIN 0x00
|
||||
#define PATCH_SEC_ENC_TYPE_AES 0x01
|
||||
#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02
|
||||
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
|
||||
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
|
||||
|
||||
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
|
||||
#define MCU_PKT_ID 0xa0
|
||||
|
||||
struct mt76_connac2_mcu_txd {
|
||||
__le32 txd[8];
|
||||
|
||||
__le16 len;
|
||||
__le16 pq_id;
|
||||
|
||||
u8 cid;
|
||||
u8 pkt_type;
|
||||
u8 set_query; /* FW don't care */
|
||||
u8 seq;
|
||||
|
||||
u8 uc_d2b0_rev;
|
||||
u8 ext_cid;
|
||||
u8 s2d_index;
|
||||
u8 ext_cid_ack;
|
||||
|
||||
u32 rsv[5];
|
||||
} __packed __aligned(4);
|
||||
|
||||
/**
|
||||
* struct mt76_connac2_mcu_uni_txd - mcu command descriptor for firmware v3
|
||||
* @txd: hardware descriptor
|
||||
* @len: total length not including txd
|
||||
* @cid: command identifier
|
||||
* @pkt_type: must be 0xa0 (cmd packet by long format)
|
||||
* @frag_n: fragment number
|
||||
* @seq: sequence number
|
||||
* @checksum: 0 mean there is no checksum
|
||||
* @s2d_index: index for command source and destination
|
||||
* Definition | value | note
|
||||
* CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM
|
||||
* CMD_S2D_IDX_C2N | 0x01 | command from WA to WM
|
||||
* CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA
|
||||
* CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM
|
||||
*
|
||||
* @option: command option
|
||||
* BIT[0]: UNI_CMD_OPT_BIT_ACK
|
||||
* set to 1 to request a fw reply
|
||||
* if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY
|
||||
* is set, mcu firmware will send response event EID = 0x01
|
||||
* (UNI_EVENT_ID_CMD_RESULT) to the host.
|
||||
* BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD
|
||||
* 0: original command
|
||||
* 1: unified command
|
||||
* BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY
|
||||
* 0: QUERY command
|
||||
* 1: SET command
|
||||
*/
|
||||
struct mt76_connac2_mcu_uni_txd {
|
||||
__le32 txd[8];
|
||||
|
||||
/* DW1 */
|
||||
__le16 len;
|
||||
__le16 cid;
|
||||
|
||||
/* DW2 */
|
||||
u8 rsv;
|
||||
u8 pkt_type;
|
||||
u8 frag_n;
|
||||
u8 seq;
|
||||
|
||||
/* DW3 */
|
||||
__le16 checksum;
|
||||
u8 s2d_index;
|
||||
u8 option;
|
||||
|
||||
/* DW4 */
|
||||
u8 rsv1[4];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt76_connac2_mcu_rxd {
|
||||
__le32 rxd[6];
|
||||
|
||||
__le16 len;
|
||||
__le16 pkt_type_id;
|
||||
|
||||
u8 eid;
|
||||
u8 seq;
|
||||
u8 rsv[2];
|
||||
|
||||
u8 ext_eid;
|
||||
u8 rsv1[2];
|
||||
u8 s2d_index;
|
||||
};
|
||||
|
||||
struct mt76_connac2_patch_hdr {
|
||||
char build_date[16];
|
||||
char platform[4];
|
||||
__be32 hw_sw_ver;
|
||||
__be32 patch_ver;
|
||||
__be16 checksum;
|
||||
u16 rsv;
|
||||
struct {
|
||||
__be32 patch_ver;
|
||||
__be32 subsys;
|
||||
__be32 feature;
|
||||
__be32 n_region;
|
||||
__be32 crc;
|
||||
u32 rsv[11];
|
||||
} desc;
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac2_patch_sec {
|
||||
__be32 type;
|
||||
__be32 offs;
|
||||
__be32 size;
|
||||
union {
|
||||
__be32 spec[13];
|
||||
struct {
|
||||
__be32 addr;
|
||||
__be32 len;
|
||||
__be32 sec_key_idx;
|
||||
__be32 align_len;
|
||||
u32 rsv[9];
|
||||
} info;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac2_fw_trailer {
|
||||
u8 chip_id;
|
||||
u8 eco_code;
|
||||
u8 n_region;
|
||||
u8 format_ver;
|
||||
u8 format_flag;
|
||||
u8 rsv[2];
|
||||
char fw_ver[10];
|
||||
char build_date[15];
|
||||
__le32 crc;
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac2_fw_region {
|
||||
__le32 decomp_crc;
|
||||
__le32 decomp_len;
|
||||
__le32 decomp_blk_sz;
|
||||
u8 rsv[4];
|
||||
__le32 addr;
|
||||
__le32 len;
|
||||
u8 feature_set;
|
||||
u8 rsv1[15];
|
||||
} __packed;
|
||||
|
||||
struct tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@ -1653,4 +1804,9 @@ int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter);
|
||||
int mt76_connac_mcu_restart(struct mt76_dev *dev);
|
||||
int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
|
||||
u8 rx_sel, u8 val);
|
||||
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
|
||||
const char *fw_wa);
|
||||
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name);
|
||||
int mt76_connac2_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq);
|
||||
#endif /* __MT76_CONNAC_MCU_H */
|
||||
|
@ -57,8 +57,11 @@ void mt76x02_mac_set_beacon(struct mt76x02_dev *dev,
|
||||
int bcn_len = dev->beacon_ops->slot_size;
|
||||
int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count);
|
||||
|
||||
if (!mt76x02_write_beacon(dev, bcn_addr, skb))
|
||||
if (!mt76x02_write_beacon(dev, bcn_addr, skb)) {
|
||||
if (!dev->beacon_data_count)
|
||||
dev->beacon_hang_check++;
|
||||
dev->beacon_data_count++;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon);
|
||||
@ -74,6 +77,7 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
|
||||
if (!dev->mt76.beacon_mask)
|
||||
dev->tbtt_count = 0;
|
||||
|
||||
dev->beacon_hang_check = 0;
|
||||
if (enable) {
|
||||
dev->mt76.beacon_mask |= BIT(mvif->idx);
|
||||
} else {
|
||||
|
@ -1044,10 +1044,9 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (++dev->beacon_hang_check < 10)
|
||||
if (dev->beacon_hang_check < 10)
|
||||
return;
|
||||
|
||||
dev->beacon_hang_check = 0;
|
||||
} else {
|
||||
u32 val = mt76_rr(dev, 0x10f4);
|
||||
if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5))))
|
||||
@ -1057,10 +1056,16 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
|
||||
dev_err(dev->mt76.dev, "MAC error detected\n");
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
|
||||
mt76x02_wait_for_txrx_idle(&dev->mt76);
|
||||
if (!mt76x02_wait_for_txrx_idle(&dev->mt76)) {
|
||||
dev_err(dev->mt76.dev, "MAC stop failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->beacon_hang_check = 0;
|
||||
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
|
||||
udelay(10);
|
||||
|
||||
out:
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
|
||||
|
||||
mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL);
|
||||
mt76_tx_queue_skb(dev, q, MT_TXQ_PSD, skb, &mvif->group_wcid,
|
||||
NULL);
|
||||
}
|
||||
spin_unlock(&q->lock);
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500,
|
||||
MT_EP_OUT_INBAND_CMD);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
if (wait_resp)
|
||||
ret = mt76x02u_mcu_wait_resp(dev, seq);
|
||||
|
@ -976,7 +976,7 @@ mt7915_rf_regval_get(void *data, u64 *val)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = le32_to_cpu(regval);
|
||||
*val = regval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -985,8 +985,9 @@ static int
|
||||
mt7915_rf_regval_set(void *data, u64 val)
|
||||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
u32 val32 = val;
|
||||
|
||||
return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true);
|
||||
return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true);
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get,
|
||||
|
@ -9,29 +9,14 @@ static int
|
||||
mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int i, err;
|
||||
|
||||
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
|
||||
ring_base = MT_WED_TX_RING_BASE;
|
||||
idx -= MT_TXQ_ID(0);
|
||||
}
|
||||
|
||||
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base,
|
||||
MT_WED_Q_TX(idx));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i <= MT_TXQ_PSD; i++)
|
||||
phy->mt76->q_tx[i] = phy->mt76->q_tx[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_tx_cleanup(struct mt7915_dev *dev)
|
||||
{
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false);
|
||||
return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, ring_base,
|
||||
MT_WED_Q_TX(idx));
|
||||
}
|
||||
|
||||
static int mt7915_poll_tx(struct napi_struct *napi, int budget)
|
||||
@ -40,8 +25,7 @@ static int mt7915_poll_tx(struct napi_struct *napi, int budget)
|
||||
|
||||
dev = container_of(napi, struct mt7915_dev, mt76.tx_napi);
|
||||
|
||||
mt7915_tx_cleanup(dev);
|
||||
|
||||
mt76_connac_tx_cleanup(&dev->mt76);
|
||||
if (napi_complete_done(napi, 0))
|
||||
mt7915_irq_enable(dev, MT_INT_TX_DONE_MCU);
|
||||
|
||||
@ -65,8 +49,8 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
|
||||
RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7915_RXQ_BAND0);
|
||||
RXQ_CONFIG(MT_RXQ_MCU, WFDMA1, MT_INT_RX_DONE_WM, MT7915_RXQ_MCU_WM);
|
||||
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA1, MT_INT_RX_DONE_WA, MT7915_RXQ_MCU_WA);
|
||||
RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_RX_DONE_BAND1, MT7915_RXQ_BAND1);
|
||||
RXQ_CONFIG(MT_RXQ_EXT_WA, WFDMA1, MT_INT_RX_DONE_WA_EXT, MT7915_RXQ_MCU_WA_EXT);
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7915_RXQ_BAND1);
|
||||
RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA1, MT_INT_RX_DONE_WA_EXT, MT7915_RXQ_MCU_WA_EXT);
|
||||
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA1, MT_INT_RX_DONE_WA_MAIN, MT7915_RXQ_MCU_WA);
|
||||
TXQ_CONFIG(0, WFDMA1, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0);
|
||||
TXQ_CONFIG(1, WFDMA1, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1);
|
||||
@ -77,8 +61,8 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
|
||||
RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0_MT7916, MT7916_RXQ_BAND0);
|
||||
RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7916_RXQ_MCU_WM);
|
||||
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7916_RXQ_MCU_WA);
|
||||
RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
|
||||
RXQ_CONFIG(MT_RXQ_EXT_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT_MT7916, MT7916_RXQ_MCU_WA_EXT);
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
|
||||
RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT_MT7916, MT7916_RXQ_MCU_WA_EXT);
|
||||
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN);
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0);
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1);
|
||||
@ -100,24 +84,33 @@ static void __mt7915_dma_prefetch(struct mt7915_dev *dev, u32 ofs)
|
||||
mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0xc0, 0x4));
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x100, 0x4));
|
||||
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x140, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x180, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs,
|
||||
PREFETCH(0x140, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs,
|
||||
PREFETCH(0x180, 0x4));
|
||||
if (!is_mt7915(&dev->mt76)) {
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x1c0, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs,
|
||||
PREFETCH(0x1c0, 0x4));
|
||||
base = 0x40;
|
||||
}
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT_WA) + ofs, PREFETCH(0x1c0 + base, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x200 + base, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT) + ofs, PREFETCH(0x240 + base, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs,
|
||||
PREFETCH(0x1c0 + base, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs,
|
||||
PREFETCH(0x200 + base, 0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs,
|
||||
PREFETCH(0x240 + base, 0x4));
|
||||
|
||||
/* for mt7915, the ring which is next the last
|
||||
* used ring must be initialized.
|
||||
*/
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
ofs += 0x4;
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x140, 0x0));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT_WA) + ofs, PREFETCH(0x200 + base, 0x0));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT) + ofs, PREFETCH(0x280 + base, 0x0));
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs,
|
||||
PREFETCH(0x140, 0x0));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs,
|
||||
PREFETCH(0x200 + base, 0x0));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs,
|
||||
PREFETCH(0x280 + base, 0x0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,20 +448,20 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
|
||||
|
||||
if (dev->dbdc_support || dev->phy.band_idx) {
|
||||
/* rx data queue for band1 */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
|
||||
MT_RXQ_ID(MT_RXQ_EXT),
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1],
|
||||
MT_RXQ_ID(MT_RXQ_BAND1),
|
||||
MT7915_RX_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_EXT) + hif1_ofs);
|
||||
MT_RXQ_RING_BASE(MT_RXQ_BAND1) + hif1_ofs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* tx free notify event from WA for band1 */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT_WA],
|
||||
MT_RXQ_ID(MT_RXQ_EXT_WA),
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
|
||||
MT_RXQ_ID(MT_RXQ_BAND1_WA),
|
||||
MT7915_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_EXT_WA) + hif1_ofs);
|
||||
MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -365,18 +365,24 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
|
||||
if (phy->mt76->cap.has_2ghz)
|
||||
if (phy->mt76->cap.has_2ghz) {
|
||||
phy->mt76->sband_2g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
phy->mt76->sband_5g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
@ -498,7 +504,7 @@ mt7915_alloc_ext_phy(struct mt7915_dev *dev)
|
||||
if (!dev->dbdc_support)
|
||||
return NULL;
|
||||
|
||||
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
|
||||
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1);
|
||||
if (!mphy)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -752,9 +758,10 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_dev *dev,
|
||||
|
||||
elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
|
||||
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
|
||||
elem->phy_cap_info[2] |= c;
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
|
||||
@ -978,7 +985,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
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,
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
|
||||
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
|
||||
@ -1031,7 +1038,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
|
||||
static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
|
||||
{
|
||||
struct mt7915_phy *phy = mt7915_ext_phy(dev);
|
||||
struct mt76_phy *mphy = dev->mt76.phy2;
|
||||
struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (!phy)
|
||||
return;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,8 @@
|
||||
#ifndef __MT7915_MAC_H
|
||||
#define __MT7915_MAC_H
|
||||
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
#define MT_CT_PARSE_LEN 72
|
||||
#define MT_CT_DMA_BUF_NUM 2
|
||||
|
||||
@ -27,289 +29,6 @@ enum rx_pkt_type {
|
||||
PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
|
||||
};
|
||||
|
||||
/* RXD DW1 */
|
||||
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
|
||||
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
|
||||
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
|
||||
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
|
||||
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
|
||||
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
|
||||
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
|
||||
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
|
||||
#define MT_RXD1_NORMAL_CM BIT(23)
|
||||
#define MT_RXD1_NORMAL_CLM BIT(24)
|
||||
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
|
||||
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
|
||||
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
|
||||
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
|
||||
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
|
||||
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
|
||||
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
|
||||
|
||||
/* RXD DW2 */
|
||||
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
|
||||
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
|
||||
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
|
||||
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
|
||||
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
|
||||
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
|
||||
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
|
||||
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
|
||||
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
|
||||
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
|
||||
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
|
||||
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
|
||||
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
|
||||
#define MT_RXD2_NORMAL_FRAG BIT(27)
|
||||
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
|
||||
#define MT_RXD2_NORMAL_NDATA BIT(29)
|
||||
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
|
||||
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
|
||||
|
||||
/* RXD DW3 */
|
||||
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
|
||||
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
|
||||
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
|
||||
#define MT_RXD3_NORMAL_U2M BIT(0)
|
||||
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
|
||||
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
|
||||
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
|
||||
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
|
||||
#define MT_RXD3_NORMAL_AMSDU BIT(22)
|
||||
#define MT_RXD3_NORMAL_MESH BIT(23)
|
||||
#define MT_RXD3_NORMAL_MHCP BIT(24)
|
||||
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
|
||||
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
|
||||
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
|
||||
#define MT_RXD3_NORMAL_MORE BIT(28)
|
||||
#define MT_RXD3_NORMAL_UNWANT BIT(29)
|
||||
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
|
||||
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
|
||||
|
||||
/* RXD DW4 */
|
||||
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
|
||||
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
|
||||
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
|
||||
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
|
||||
|
||||
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
|
||||
#define MT_RXD4_NORMAL_CLS BIT(10)
|
||||
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
|
||||
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
|
||||
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
|
||||
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
|
||||
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
|
||||
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
|
||||
|
||||
#define MT_RXV_HDR_BAND_IDX BIT(24)
|
||||
|
||||
/* RXD GROUP4 */
|
||||
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
|
||||
#define MT_RXD6_TA_LO GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD7_TA_HI GENMASK(31, 0)
|
||||
|
||||
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
|
||||
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
|
||||
|
||||
/* P-RXV */
|
||||
#define MT_PRXV_TX_RATE GENMASK(6, 0)
|
||||
#define MT_PRXV_TX_DCM BIT(4)
|
||||
#define MT_PRXV_TX_ER_SU_106T BIT(5)
|
||||
#define MT_PRXV_NSTS GENMASK(9, 7)
|
||||
#define MT_PRXV_TXBF BIT(10)
|
||||
#define MT_PRXV_HT_AD_CODE BIT(11)
|
||||
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
|
||||
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
|
||||
#define MT_PRXV_RCPI3 GENMASK(31, 24)
|
||||
#define MT_PRXV_RCPI2 GENMASK(23, 16)
|
||||
#define MT_PRXV_RCPI1 GENMASK(15, 8)
|
||||
#define MT_PRXV_RCPI0 GENMASK(7, 0)
|
||||
#define MT_PRXV_HT_SHORT_GI GENMASK(16, 15)
|
||||
#define MT_PRXV_HT_STBC GENMASK(23, 22)
|
||||
#define MT_PRXV_TX_MODE GENMASK(27, 24)
|
||||
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
|
||||
#define MT_PRXV_DCM BIT(17)
|
||||
#define MT_PRXV_NUM_RX BIT(20, 18)
|
||||
|
||||
/* C-RXV */
|
||||
#define MT_CRXV_HT_STBC GENMASK(1, 0)
|
||||
#define MT_CRXV_TX_MODE GENMASK(7, 4)
|
||||
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
|
||||
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
|
||||
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
|
||||
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
|
||||
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
|
||||
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
|
||||
#define MT_CRXV_HE_UPLINK BIT(31)
|
||||
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
|
||||
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
|
||||
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
|
||||
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
|
||||
|
||||
#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
|
||||
|
||||
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
|
||||
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
|
||||
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
|
||||
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
|
||||
|
||||
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
|
||||
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
|
||||
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
|
||||
#define MT_CRXV_HE_DOPPLER BIT(16)
|
||||
|
||||
#define MT_CRXV_SNR GENMASK(18, 13)
|
||||
#define MT_CRXV_FOE_LO GENMASK(31, 19)
|
||||
#define MT_CRXV_FOE_HI GENMASK(6, 0)
|
||||
#define MT_CRXV_FOE_SHIFT 13
|
||||
|
||||
enum tx_header_format {
|
||||
MT_HDR_FORMAT_802_3,
|
||||
MT_HDR_FORMAT_CMD,
|
||||
MT_HDR_FORMAT_802_11,
|
||||
MT_HDR_FORMAT_802_11_EXT,
|
||||
};
|
||||
|
||||
enum tx_pkt_type {
|
||||
MT_TX_TYPE_CT,
|
||||
MT_TX_TYPE_SF,
|
||||
MT_TX_TYPE_CMD,
|
||||
MT_TX_TYPE_FW,
|
||||
};
|
||||
|
||||
enum tx_port_idx {
|
||||
MT_TX_PORT_IDX_LMAC,
|
||||
MT_TX_PORT_IDX_MCU
|
||||
};
|
||||
|
||||
enum tx_mcu_port_q_idx {
|
||||
MT_TX_MCU_PORT_RX_Q0 = 0x20,
|
||||
MT_TX_MCU_PORT_RX_Q1,
|
||||
MT_TX_MCU_PORT_RX_Q2,
|
||||
MT_TX_MCU_PORT_RX_Q3,
|
||||
MT_TX_MCU_PORT_RX_FWDL = 0x3e
|
||||
};
|
||||
|
||||
#define MT_CT_INFO_APPLY_TXD BIT(0)
|
||||
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
|
||||
#define MT_CT_INFO_MGMT_FRAME BIT(2)
|
||||
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
|
||||
#define MT_CT_INFO_HSR2_TX BIT(4)
|
||||
#define MT_CT_INFO_FROM_HOST BIT(7)
|
||||
|
||||
#define MT_TXD_SIZE (8 * 4)
|
||||
|
||||
#define MT_TXD0_Q_IDX GENMASK(31, 25)
|
||||
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
|
||||
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
|
||||
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
|
||||
|
||||
#define MT_TXD1_LONG_FORMAT BIT(31)
|
||||
#define MT_TXD1_TGID BIT(30)
|
||||
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
|
||||
#define MT_TXD1_AMSDU BIT(23)
|
||||
#define MT_TXD1_TID GENMASK(22, 20)
|
||||
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
|
||||
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
|
||||
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
|
||||
#define MT_TXD1_ETH_802_3 BIT(15)
|
||||
#define MT_TXD1_VTA BIT(10)
|
||||
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
|
||||
|
||||
#define MT_TXD2_FIX_RATE BIT(31)
|
||||
#define MT_TXD2_FIXED_RATE BIT(30)
|
||||
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
|
||||
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
|
||||
#define MT_TXD2_FRAG GENMASK(15, 14)
|
||||
#define MT_TXD2_HTC_VLD BIT(13)
|
||||
#define MT_TXD2_DURATION BIT(12)
|
||||
#define MT_TXD2_BIP BIT(11)
|
||||
#define MT_TXD2_MULTICAST BIT(10)
|
||||
#define MT_TXD2_RTS BIT(9)
|
||||
#define MT_TXD2_SOUNDING BIT(8)
|
||||
#define MT_TXD2_NDPA BIT(7)
|
||||
#define MT_TXD2_NDP BIT(6)
|
||||
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
|
||||
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
|
||||
|
||||
#define MT_TXD3_SN_VALID BIT(31)
|
||||
#define MT_TXD3_PN_VALID BIT(30)
|
||||
#define MT_TXD3_SW_POWER_MGMT BIT(29)
|
||||
#define MT_TXD3_BA_DISABLE BIT(28)
|
||||
#define MT_TXD3_SEQ GENMASK(27, 16)
|
||||
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
|
||||
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
|
||||
#define MT_TXD3_TIMING_MEASURE BIT(5)
|
||||
#define MT_TXD3_DAS BIT(4)
|
||||
#define MT_TXD3_EEOSP BIT(3)
|
||||
#define MT_TXD3_EMRD BIT(2)
|
||||
#define MT_TXD3_PROTECT_FRAME BIT(1)
|
||||
#define MT_TXD3_NO_ACK BIT(0)
|
||||
|
||||
#define MT_TXD4_PN_LOW GENMASK(31, 0)
|
||||
|
||||
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
|
||||
#define MT_TXD5_MD BIT(15)
|
||||
#define MT_TXD5_ADD_BA BIT(14)
|
||||
#define MT_TXD5_TX_STATUS_HOST BIT(10)
|
||||
#define MT_TXD5_TX_STATUS_MCU BIT(9)
|
||||
#define MT_TXD5_TX_STATUS_FMT BIT(8)
|
||||
#define MT_TXD5_PID GENMASK(7, 0)
|
||||
|
||||
#define MT_TXD6_TX_IBF BIT(31)
|
||||
#define MT_TXD6_TX_EBF BIT(30)
|
||||
#define MT_TXD6_TX_RATE GENMASK(29, 16)
|
||||
#define MT_TXD6_SGI GENMASK(15, 14)
|
||||
#define MT_TXD6_HELTF GENMASK(13, 12)
|
||||
#define MT_TXD6_LDPC BIT(11)
|
||||
#define MT_TXD6_SPE_ID_IDX BIT(10)
|
||||
#define MT_TXD6_ANT_ID GENMASK(7, 4)
|
||||
#define MT_TXD6_DYN_BW BIT(3)
|
||||
#define MT_TXD6_FIXED_BW BIT(2)
|
||||
#define MT_TXD6_BW GENMASK(1, 0)
|
||||
|
||||
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
|
||||
#define MT_TXD7_UDP_TCP_SUM BIT(29)
|
||||
#define MT_TXD7_IP_SUM BIT(28)
|
||||
|
||||
#define MT_TXD7_TYPE GENMASK(21, 20)
|
||||
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
|
||||
|
||||
#define MT_TXD7_PSE_FID GENMASK(27, 16)
|
||||
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
|
||||
#define MT_TXD7_HW_AMSDU BIT(10)
|
||||
#define MT_TXD7_TX_TIME GENMASK(9, 0)
|
||||
|
||||
#define MT_TX_RATE_STBC BIT(13)
|
||||
#define MT_TX_RATE_NSS GENMASK(12, 10)
|
||||
#define MT_TX_RATE_MODE GENMASK(9, 6)
|
||||
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
|
||||
#define MT_TX_RATE_DCM BIT(4)
|
||||
/* VHT/HE only use bits 0-3 */
|
||||
#define MT_TX_RATE_IDX GENMASK(5, 0)
|
||||
|
||||
#define MT_TXP_MAX_BUF_NUM 6
|
||||
|
||||
struct mt7915_txp {
|
||||
__le16 flags;
|
||||
__le16 token;
|
||||
u8 bss_idx;
|
||||
__le16 rept_wds_wcid;
|
||||
u8 nbuf;
|
||||
__le32 buf[MT_TXP_MAX_BUF_NUM];
|
||||
__le16 len[MT_TXP_MAX_BUF_NUM];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7915_tx_free {
|
||||
__le16 rx_byte_cnt;
|
||||
__le16 ctrl;
|
||||
__le32 txd;
|
||||
__le32 info[];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define MT_TX_FREE_VER GENMASK(18, 16)
|
||||
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
|
||||
#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
|
||||
@ -324,41 +43,6 @@ struct mt7915_tx_free {
|
||||
/* will support this field in further revision */
|
||||
#define MT_TX_FREE_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXS0_FIXED_RATE BIT(31)
|
||||
#define MT_TXS0_BW GENMASK(30, 29)
|
||||
#define MT_TXS0_TID GENMASK(28, 26)
|
||||
#define MT_TXS0_AMPDU BIT(25)
|
||||
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
|
||||
#define MT_TXS0_BA_ERROR BIT(22)
|
||||
#define MT_TXS0_PS_FLAG BIT(21)
|
||||
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
|
||||
#define MT_TXS0_BIP_ERROR BIT(19)
|
||||
|
||||
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
|
||||
#define MT_TXS0_RTS_TIMEOUT BIT(17)
|
||||
#define MT_TXS0_ACK_TIMEOUT BIT(16)
|
||||
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
|
||||
|
||||
#define MT_TXS0_TX_STATUS_HOST BIT(15)
|
||||
#define MT_TXS0_TX_STATUS_MCU BIT(14)
|
||||
#define MT_TXS0_TX_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXS1_SEQNO GENMASK(31, 20)
|
||||
#define MT_TXS1_RESP_RATE GENMASK(19, 16)
|
||||
#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
|
||||
#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
|
||||
|
||||
#define MT_TXS2_BF_STATUS GENMASK(31, 30)
|
||||
#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27)
|
||||
#define MT_TXS2_SHARED_ANTENNA BIT(26)
|
||||
#define MT_TXS2_WCID GENMASK(25, 16)
|
||||
#define MT_TXS2_TX_DELAY GENMASK(15, 0)
|
||||
|
||||
#define MT_TXS3_PID GENMASK(31, 24)
|
||||
#define MT_TXS3_ANT_ID GENMASK(23, 0)
|
||||
|
||||
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
|
||||
|
||||
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
|
||||
#define MT_TXS5_F0_QOS BIT(30)
|
||||
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
|
||||
@ -414,17 +98,4 @@ struct mt7915_dfs_radar_spec {
|
||||
struct mt7915_dfs_pattern radar_pattern[16];
|
||||
};
|
||||
|
||||
static inline struct mt7915_txp *
|
||||
mt7915_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
u8 *txwi;
|
||||
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
txwi = mt76_get_txwi_ptr(dev, t);
|
||||
|
||||
return (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -227,7 +227,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
||||
INIT_LIST_HEAD(&mvif->sta.rc_list);
|
||||
INIT_LIST_HEAD(&mvif->sta.poll_list);
|
||||
mvif->sta.wcid.idx = idx;
|
||||
mvif->sta.wcid.ext_phy = ext_phy;
|
||||
mvif->sta.wcid.phy_idx = ext_phy;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
@ -235,7 +235,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
||||
mt7915_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = idx;
|
||||
@ -251,6 +250,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
mt7915_mcu_add_bss_info(phy, vif, true);
|
||||
mt7915_mcu_add_sta(dev, vif, NULL, true);
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
@ -661,7 +661,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
msta->vif = mvif;
|
||||
msta->wcid.sta = 1;
|
||||
msta->wcid.idx = idx;
|
||||
msta->wcid.ext_phy = ext_phy;
|
||||
msta->wcid.phy_idx = ext_phy;
|
||||
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
msta->jiffies = jiffies;
|
||||
|
||||
@ -1147,8 +1147,15 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||
"rx_fifo_full_cnt",
|
||||
"rx_mpdu_cnt",
|
||||
"channel_idle_cnt",
|
||||
"primary_cca_busy_time",
|
||||
"secondary_cca_busy_time",
|
||||
"primary_energy_detect_time",
|
||||
"cck_mdrdy_time",
|
||||
"ofdm_mdrdy_time",
|
||||
"green_mdrdy_time",
|
||||
"rx_vector_mismatch_cnt",
|
||||
"rx_delimiter_fail_cnt",
|
||||
"rx_mrdy_cnt",
|
||||
"rx_len_mismatch_cnt",
|
||||
"rx_ampdu_cnt",
|
||||
"rx_ampdu_bytes_cnt",
|
||||
@ -1288,8 +1295,15 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
|
||||
data[ei++] = mib->rx_fifo_full_cnt;
|
||||
data[ei++] = mib->rx_mpdu_cnt;
|
||||
data[ei++] = mib->channel_idle_cnt;
|
||||
data[ei++] = mib->primary_cca_busy_time;
|
||||
data[ei++] = mib->secondary_cca_busy_time;
|
||||
data[ei++] = mib->primary_energy_detect_time;
|
||||
data[ei++] = mib->cck_mdrdy_time;
|
||||
data[ei++] = mib->ofdm_mdrdy_time;
|
||||
data[ei++] = mib->green_mdrdy_time;
|
||||
data[ei++] = mib->rx_vector_mismatch_cnt;
|
||||
data[ei++] = mib->rx_delimiter_fail_cnt;
|
||||
data[ei++] = mib->rx_mrdy_cnt;
|
||||
data[ei++] = mib->rx_len_mismatch_cnt;
|
||||
data[ei++] = mib->rx_ampdu_cnt;
|
||||
data[ei++] = mib->rx_ampdu_bytes_cnt;
|
||||
|
@ -1,69 +1,12 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/fs.h>
|
||||
#include "mt7915.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
struct mt7915_patch_hdr {
|
||||
char build_date[16];
|
||||
char platform[4];
|
||||
__be32 hw_sw_ver;
|
||||
__be32 patch_ver;
|
||||
__be16 checksum;
|
||||
u16 reserved;
|
||||
struct {
|
||||
__be32 patch_ver;
|
||||
__be32 subsys;
|
||||
__be32 feature;
|
||||
__be32 n_region;
|
||||
__be32 crc;
|
||||
u32 reserved[11];
|
||||
} desc;
|
||||
} __packed;
|
||||
|
||||
struct mt7915_patch_sec {
|
||||
__be32 type;
|
||||
__be32 offs;
|
||||
__be32 size;
|
||||
union {
|
||||
__be32 spec[13];
|
||||
struct {
|
||||
__be32 addr;
|
||||
__be32 len;
|
||||
__be32 sec_key_idx;
|
||||
__be32 align_len;
|
||||
u32 reserved[9];
|
||||
} info;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct mt7915_fw_trailer {
|
||||
u8 chip_id;
|
||||
u8 eco_code;
|
||||
u8 n_region;
|
||||
u8 format_ver;
|
||||
u8 format_flag;
|
||||
u8 reserved[2];
|
||||
char fw_ver[10];
|
||||
char build_date[15];
|
||||
u32 crc;
|
||||
} __packed;
|
||||
|
||||
struct mt7915_fw_region {
|
||||
__le32 decomp_crc;
|
||||
__le32 decomp_len;
|
||||
__le32 decomp_blk_sz;
|
||||
u8 reserved[4];
|
||||
__le32 addr;
|
||||
__le32 len;
|
||||
u8 feature_set;
|
||||
u8 reserved1[15];
|
||||
} __packed;
|
||||
|
||||
#define fw_name(_dev, name, ...) ({ \
|
||||
char *_fw; \
|
||||
switch (mt76_chip(&(_dev)->mt76)) { \
|
||||
@ -207,7 +150,7 @@ static int
|
||||
mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
struct sk_buff *skb, int seq)
|
||||
{
|
||||
struct mt7915_mcu_rxd *rxd;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
int ret = 0;
|
||||
|
||||
if (!skb) {
|
||||
@ -216,7 +159,7 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
rxd = (struct mt7915_mcu_rxd *)skb->data;
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
if (seq != rxd->seq)
|
||||
return -EAGAIN;
|
||||
|
||||
@ -227,7 +170,7 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
skb_pull(skb, sizeof(*rxd) + 4);
|
||||
ret = le32_to_cpu(*(__le32 *)skb->data);
|
||||
} else {
|
||||
skb_pull(skb, sizeof(struct mt7915_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -238,69 +181,20 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
struct mt7915_mcu_txd *mcu_txd;
|
||||
enum mt76_mcuq_id qid;
|
||||
__le32 *txd;
|
||||
u32 val;
|
||||
u8 seq;
|
||||
int ret;
|
||||
|
||||
/* TODO: make dynamic based on msg type */
|
||||
mdev->mcu.timeout = 20 * HZ;
|
||||
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, wait_seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
seq = ++dev->mt76.mcu.msg_seq & 0xf;
|
||||
if (!seq)
|
||||
seq = ++dev->mt76.mcu.msg_seq & 0xf;
|
||||
|
||||
if (cmd == MCU_CMD(FW_SCATTER)) {
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
qid = MT_MCUQ_FWDL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mcu_txd = (struct mt7915_mcu_txd *)skb_push(skb, sizeof(*mcu_txd));
|
||||
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
|
||||
else if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
|
||||
qid = MT_MCUQ_WA;
|
||||
else
|
||||
qid = MT_MCUQ_WM;
|
||||
|
||||
txd = mcu_txd->txd;
|
||||
|
||||
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
|
||||
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |
|
||||
FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);
|
||||
txd[0] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);
|
||||
txd[1] = cpu_to_le32(val);
|
||||
|
||||
mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
|
||||
mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,
|
||||
MT_TX_MCU_PORT_RX_Q0));
|
||||
mcu_txd->pkt_type = MCU_PKT_ID;
|
||||
mcu_txd->seq = seq;
|
||||
|
||||
mcu_txd->cid = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
|
||||
mcu_txd->set_query = MCU_Q_NA;
|
||||
mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
|
||||
if (mcu_txd->ext_cid) {
|
||||
mcu_txd->ext_cid_ack = 1;
|
||||
|
||||
/* do not use Q_SET for efuse */
|
||||
if (cmd & __MCU_CMD_FIELD_QUERY)
|
||||
mcu_txd->set_query = MCU_Q_QUERY;
|
||||
else
|
||||
mcu_txd->set_query = MCU_Q_SET;
|
||||
}
|
||||
|
||||
if (cmd & __MCU_CMD_FIELD_WA)
|
||||
mcu_txd->s2d_index = MCU_S2D_H2C;
|
||||
else
|
||||
mcu_txd->s2d_index = MCU_S2D_H2N;
|
||||
|
||||
exit:
|
||||
if (wait_seq)
|
||||
*wait_seq = seq;
|
||||
|
||||
return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0);
|
||||
}
|
||||
|
||||
@ -334,8 +228,8 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
c = (struct mt7915_mcu_csa_notify *)skb->data;
|
||||
|
||||
if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
@ -353,8 +247,8 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
|
||||
return;
|
||||
|
||||
if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
phy = (struct mt7915_phy *)mphy->priv;
|
||||
phy->throttle_state = t->ctrl.duty.duty_cycle;
|
||||
@ -368,8 +262,8 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
r = (struct mt7915_mcu_rdd_report *)skb->data;
|
||||
|
||||
if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (r->band_idx == MT_RX_SEL2)
|
||||
cfg80211_background_radar_event(mphy->hw->wiphy,
|
||||
@ -383,10 +277,12 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
static void
|
||||
mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
|
||||
const char *data = (char *)&rxd[1];
|
||||
const char *type;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
int len = skb->len - sizeof(*rxd);
|
||||
const char *data, *type;
|
||||
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
data = (char *)&rxd[1];
|
||||
|
||||
switch (rxd->s2d_index) {
|
||||
case 0:
|
||||
@ -423,8 +319,8 @@ mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
b = (struct mt7915_mcu_bcc_notify *)skb->data;
|
||||
|
||||
if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
@ -434,8 +330,9 @@ mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
static void
|
||||
mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
switch (rxd->ext_eid) {
|
||||
case MCU_EXT_EVENT_THERMAL_PROTECT:
|
||||
mt7915_mcu_rx_thermal_notify(dev, skb);
|
||||
@ -460,8 +357,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
static void
|
||||
mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
switch (rxd->eid) {
|
||||
case MCU_EVENT_EXT:
|
||||
mt7915_mcu_rx_ext_event(dev, skb);
|
||||
@ -474,8 +372,9 @@ mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
|
||||
rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
|
||||
rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
|
||||
@ -927,8 +826,8 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif)
|
||||
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
|
||||
@ -946,7 +845,8 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
||||
muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
|
||||
mvif->cap.vht_mu_ebfer ||
|
||||
mvif->cap.vht_mu_ebfee;
|
||||
muru->cfg.mimo_ul_en = true;
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
muru->cfg.mimo_ul_en = true;
|
||||
muru->cfg.ofdma_dl_en = true;
|
||||
|
||||
if (sta->deflink.vht_cap.vht_supported)
|
||||
@ -1720,7 +1620,8 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
return PTR_ERR(skb);
|
||||
|
||||
/* starec basic */
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable, true);
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable,
|
||||
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
@ -1748,7 +1649,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
/* starec he */
|
||||
mt7915_mcu_sta_he_tlv(skb, sta, vif);
|
||||
/* starec muru */
|
||||
mt7915_mcu_sta_muru_tlv(skb, sta, vif);
|
||||
mt7915_mcu_sta_muru_tlv(dev, skb, sta, vif);
|
||||
/* starec bfee */
|
||||
mt7915_mcu_sta_bfee_tlv(dev, skb, vif, sta);
|
||||
}
|
||||
@ -1910,8 +1811,8 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
buf = (u8 *)tlv + sizeof(*cont);
|
||||
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
BSS_CHANGED_BEACON);
|
||||
mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
0, BSS_CHANGED_BEACON);
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
}
|
||||
|
||||
@ -2031,12 +1932,17 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
|
||||
info->control.vif = vif;
|
||||
info->band = band;
|
||||
|
||||
if (ext_phy)
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
|
||||
|
||||
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
|
||||
len = (len & 0x3) ? ((len | 0x3) + 1) : len;
|
||||
|
||||
if (len > (MT7915_MAX_BSS_OFFLOAD_SIZE - rskb->len)) {
|
||||
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
|
||||
len, &bcn->sub_ntlv, &bcn->len);
|
||||
discov = (struct bss_info_inband_discovery *)tlv;
|
||||
@ -2049,8 +1955,8 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
|
||||
|
||||
buf = (u8 *)tlv + sizeof(*discov);
|
||||
|
||||
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
changed);
|
||||
mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
0, changed);
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
@ -2059,7 +1965,6 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int en, u32 changed)
|
||||
{
|
||||
#define MAX_BEACON_SIZE 512
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
@ -2068,7 +1973,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb, *rskb;
|
||||
struct tlv *tlv;
|
||||
struct bss_info_bcn *bcn;
|
||||
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
|
||||
int len = MT7915_MAX_BSS_OFFLOAD_SIZE;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
|
||||
if (vif->bss_conf.nontransmitted)
|
||||
@ -2090,16 +1995,14 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
|
||||
if (skb->len > MT7915_MAX_BEACON_SIZE - MT_TXD_SIZE) {
|
||||
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ext_phy) {
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
}
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
|
||||
|
||||
mt7915_mcu_beacon_check_caps(phy, vif, skb);
|
||||
|
||||
@ -2134,203 +2037,6 @@ static int mt7915_driver_own(struct mt7915_dev *dev, u8 band)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7915_load_patch(struct mt7915_dev *dev)
|
||||
{
|
||||
const struct mt7915_patch_hdr *hdr;
|
||||
const struct firmware *fw = NULL;
|
||||
int i, ret, sem;
|
||||
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 1);
|
||||
switch (sem) {
|
||||
case PATCH_IS_DL:
|
||||
return 0;
|
||||
case PATCH_NOT_DL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, fw_name_var(dev, ROM_PATCH),
|
||||
dev->mt76.dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt7915_patch_hdr *)(fw->data);
|
||||
|
||||
dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
|
||||
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
|
||||
|
||||
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
|
||||
struct mt7915_patch_sec *sec;
|
||||
const u8 *dl;
|
||||
u32 len, addr;
|
||||
|
||||
sec = (struct mt7915_patch_sec *)(fw->data + sizeof(*hdr) +
|
||||
i * sizeof(*sec));
|
||||
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
|
||||
PATCH_SEC_TYPE_INFO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = be32_to_cpu(sec->info.addr);
|
||||
len = be32_to_cpu(sec->info.len);
|
||||
dl = fw->data + be32_to_cpu(sec->offs);
|
||||
|
||||
ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
|
||||
DL_MODE_NEED_RSP);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Download request failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
|
||||
dl, len, 4096);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to send patch\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_start_patch(&dev->mt76);
|
||||
if (ret)
|
||||
dev_err(dev->mt76.dev, "Failed to start patch\n");
|
||||
|
||||
out:
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 0);
|
||||
switch (sem) {
|
||||
case PATCH_REL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ret = -EAGAIN;
|
||||
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
|
||||
break;
|
||||
}
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev,
|
||||
const struct mt7915_fw_trailer *hdr,
|
||||
const u8 *data, bool is_wa)
|
||||
{
|
||||
int i, offset = 0;
|
||||
u32 override = 0, option = 0;
|
||||
|
||||
for (i = 0; i < hdr->n_region; i++) {
|
||||
const struct mt7915_fw_region *region;
|
||||
int err;
|
||||
u32 len, addr, mode;
|
||||
|
||||
region = (const struct mt7915_fw_region *)((const u8 *)hdr -
|
||||
(hdr->n_region - i) * sizeof(*region));
|
||||
mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
|
||||
region->feature_set, is_wa);
|
||||
len = le32_to_cpu(region->len);
|
||||
addr = le32_to_cpu(region->addr);
|
||||
|
||||
if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
|
||||
override = addr;
|
||||
|
||||
err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
|
||||
mode);
|
||||
if (err) {
|
||||
dev_err(dev->mt76.dev, "Download request failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
|
||||
data + offset, len, 4096);
|
||||
if (err) {
|
||||
dev_err(dev->mt76.dev, "Failed to send firmware.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
if (override)
|
||||
option |= FW_START_OVERRIDE;
|
||||
|
||||
if (is_wa)
|
||||
option |= FW_START_WORKING_PDA_CR4;
|
||||
|
||||
return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
|
||||
}
|
||||
|
||||
static int mt7915_load_ram(struct mt7915_dev *dev)
|
||||
{
|
||||
const struct mt7915_fw_trailer *hdr;
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, fw_name_var(dev, FIRMWARE_WM),
|
||||
dev->mt76.dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size -
|
||||
sizeof(*hdr));
|
||||
|
||||
dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
|
||||
hdr->fw_ver, hdr->build_date);
|
||||
|
||||
ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, false);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
ret = request_firmware(&fw, fw_name(dev, FIRMWARE_WA),
|
||||
dev->mt76.dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size -
|
||||
sizeof(*hdr));
|
||||
|
||||
dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
|
||||
hdr->fw_ver, hdr->build_date);
|
||||
|
||||
ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, true);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(dev->mt76.hw->wiphy->fw_version,
|
||||
sizeof(dev->mt76.hw->wiphy->fw_version),
|
||||
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_firmware_state(struct mt7915_dev *dev, bool wa)
|
||||
{
|
||||
@ -2361,11 +2067,12 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt7915_load_patch(dev);
|
||||
ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7915_load_ram(dev);
|
||||
ret = mt76_connac2_load_ram(&dev->mt76, fw_name_var(dev, FIRMWARE_WM),
|
||||
fw_name(dev, FIRMWARE_WA));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2528,7 +2235,7 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
|
||||
int mt7915_mcu_init(struct mt7915_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7915_mcu_ops = {
|
||||
.headroom = sizeof(struct mt7915_mcu_txd),
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7915_mcu_send_message,
|
||||
.mcu_parse_response = mt7915_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
@ -2685,7 +2392,7 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif)
|
||||
struct edca *e = &req.edca[ac];
|
||||
|
||||
e->set = WMM_PARAM_SET;
|
||||
e->queue = ac + mvif->mt76.wmm_idx * MT7915_MAX_WMM_SETS;
|
||||
e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
|
||||
e->aifs = q->aifs;
|
||||
e->txop = cpu_to_le16(q->txop);
|
||||
|
||||
|
@ -6,25 +6,6 @@
|
||||
|
||||
#include "../mt76_connac_mcu.h"
|
||||
|
||||
struct mt7915_mcu_txd {
|
||||
__le32 txd[8];
|
||||
|
||||
__le16 len;
|
||||
__le16 pq_id;
|
||||
|
||||
u8 cid;
|
||||
u8 pkt_type;
|
||||
u8 set_query; /* FW don't care */
|
||||
u8 seq;
|
||||
|
||||
u8 uc_d2b0_rev;
|
||||
u8 ext_cid;
|
||||
u8 s2d_index;
|
||||
u8 ext_cid_ack;
|
||||
|
||||
u32 reserved[5];
|
||||
} __packed __aligned(4);
|
||||
|
||||
enum {
|
||||
MCU_ATE_SET_TRX = 0x1,
|
||||
MCU_ATE_SET_FREQ_OFFSET = 0xa,
|
||||
@ -32,21 +13,6 @@ enum {
|
||||
MCU_ATE_CLEAN_TXQUEUE = 0x1c,
|
||||
};
|
||||
|
||||
struct mt7915_mcu_rxd {
|
||||
__le32 rxd[6];
|
||||
|
||||
__le16 len;
|
||||
__le16 pkt_type_id;
|
||||
|
||||
u8 eid;
|
||||
u8 seq;
|
||||
__le16 __rsv;
|
||||
|
||||
u8 ext_eid;
|
||||
u8 __rsv1[2];
|
||||
u8 s2d_index;
|
||||
};
|
||||
|
||||
struct mt7915_mcu_thermal_ctrl {
|
||||
u8 ctrl_id;
|
||||
u8 band_idx;
|
||||
@ -63,7 +29,7 @@ struct mt7915_mcu_thermal_ctrl {
|
||||
} __packed;
|
||||
|
||||
struct mt7915_mcu_thermal_notify {
|
||||
struct mt7915_mcu_rxd rxd;
|
||||
struct mt76_connac2_mcu_rxd rxd;
|
||||
|
||||
struct mt7915_mcu_thermal_ctrl ctrl;
|
||||
__le32 temperature;
|
||||
@ -71,7 +37,7 @@ struct mt7915_mcu_thermal_notify {
|
||||
} __packed;
|
||||
|
||||
struct mt7915_mcu_csa_notify {
|
||||
struct mt7915_mcu_rxd rxd;
|
||||
struct mt76_connac2_mcu_rxd rxd;
|
||||
|
||||
u8 omac_idx;
|
||||
u8 csa_count;
|
||||
@ -80,7 +46,7 @@ struct mt7915_mcu_csa_notify {
|
||||
} __packed;
|
||||
|
||||
struct mt7915_mcu_bcc_notify {
|
||||
struct mt7915_mcu_rxd rxd;
|
||||
struct mt76_connac2_mcu_rxd rxd;
|
||||
|
||||
u8 band_idx;
|
||||
u8 omac_idx;
|
||||
@ -89,7 +55,7 @@ struct mt7915_mcu_bcc_notify {
|
||||
} __packed;
|
||||
|
||||
struct mt7915_mcu_rdd_report {
|
||||
struct mt7915_mcu_rxd rxd;
|
||||
struct mt76_connac2_mcu_rxd rxd;
|
||||
|
||||
u8 band_idx;
|
||||
u8 long_detected;
|
||||
@ -267,9 +233,6 @@ struct mt7915_mcu_muru_stats {
|
||||
#define WMM_TXOP_SET BIT(3)
|
||||
#define WMM_PARAM_SET GENMASK(3, 0)
|
||||
|
||||
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
|
||||
#define MCU_PKT_ID 0xa0
|
||||
|
||||
enum {
|
||||
MCU_FW_LOG_WM,
|
||||
MCU_FW_LOG_WA,
|
||||
@ -489,6 +452,12 @@ enum {
|
||||
SER_RECOVER
|
||||
};
|
||||
|
||||
#define MT7915_MAX_BEACON_SIZE 512
|
||||
#define MT7915_MAX_INBAND_FRAME_SIZE 256
|
||||
#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \
|
||||
MT7915_MAX_INBAND_FRAME_SIZE + \
|
||||
MT7915_BEACON_UPDATE_SIZE)
|
||||
|
||||
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct bss_info_omac) + \
|
||||
sizeof(struct bss_info_basic) +\
|
||||
|
@ -591,8 +591,8 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
|
||||
if (intr & MT_INT_RX(MT_RXQ_MAIN))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
|
||||
|
||||
if (intr & MT_INT_RX(MT_RXQ_EXT))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_EXT]);
|
||||
if (intr & MT_INT_RX(MT_RXQ_BAND1))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1]);
|
||||
|
||||
if (intr & MT_INT_RX(MT_RXQ_MCU))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);
|
||||
@ -604,8 +604,8 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
|
||||
(intr & MT_INT_RX(MT_RXQ_MAIN_WA)))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN_WA]);
|
||||
|
||||
if (intr & MT_INT_RX(MT_RXQ_EXT_WA))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_EXT_WA]);
|
||||
if (intr & MT_INT_RX(MT_RXQ_BAND1_WA))
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1_WA]);
|
||||
|
||||
if (intr & MT_INT_MCU_CMD) {
|
||||
u32 val = mt76_rr(dev, MT_MCU_CMD);
|
||||
@ -645,14 +645,14 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
/* txwi_size = txd size + txp size */
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp),
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
|
||||
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.token_size = MT7915_TOKEN_SIZE,
|
||||
.tx_prepare_skb = mt7915_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7915_tx_complete_skb,
|
||||
.tx_complete_skb = mt76_connac_tx_complete_skb,
|
||||
.rx_skb = mt7915_queue_rx_skb,
|
||||
.rx_check = mt7915_rx_check,
|
||||
.rx_poll_complete = mt7915_rx_poll_complete,
|
||||
@ -661,16 +661,11 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
|
||||
.sta_remove = mt7915_mac_sta_remove,
|
||||
.update_survey = mt7915_update_channel,
|
||||
};
|
||||
struct ieee80211_ops *ops;
|
||||
struct mt7915_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
int ret;
|
||||
|
||||
ops = devm_kmemdup(pdev, &mt7915_ops, sizeof(mt7915_ops), GFP_KERNEL);
|
||||
if (!ops)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, &drv_ops);
|
||||
mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7915_ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "regs.h"
|
||||
|
||||
#define MT7915_MAX_INTERFACES 19
|
||||
#define MT7915_MAX_WMM_SETS 4
|
||||
#define MT7915_WTBL_SIZE 288
|
||||
#define MT7916_WTBL_SIZE 544
|
||||
#define MT7915_WTBL_RESERVED (mt7915_wtbl_size(dev) - 1)
|
||||
@ -67,7 +66,7 @@
|
||||
#define MT7915_MAX_TWT_AGRT 16
|
||||
#define MT7915_MAX_STA_TWT_AGRT 8
|
||||
#define MT7915_MIN_TWT_DUR 64
|
||||
#define MT7915_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 2)
|
||||
#define MT7915_MAX_QUEUE (MT_RXQ_BAND2 + __MT_MCUQ_MAX + 2)
|
||||
|
||||
struct mt7915_vif;
|
||||
struct mt7915_sta;
|
||||
@ -200,8 +199,15 @@ struct mib_stats {
|
||||
/* rx stats */
|
||||
u32 rx_fifo_full_cnt;
|
||||
u32 channel_idle_cnt;
|
||||
u32 primary_cca_busy_time;
|
||||
u32 secondary_cca_busy_time;
|
||||
u32 primary_energy_detect_time;
|
||||
u32 cck_mdrdy_time;
|
||||
u32 ofdm_mdrdy_time;
|
||||
u32 green_mdrdy_time;
|
||||
u32 rx_vector_mismatch_cnt;
|
||||
u32 rx_delimiter_fail_cnt;
|
||||
u32 rx_mrdy_cnt;
|
||||
u32 rx_len_mismatch_cnt;
|
||||
u32 rx_mpdu_cnt;
|
||||
u32 rx_ampdu_cnt;
|
||||
@ -341,20 +347,6 @@ enum {
|
||||
__MT_WFDMA_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_CTX0,
|
||||
MT_HIF0 = 0x0,
|
||||
|
||||
MT_LMAC_AC00 = 0x0,
|
||||
MT_LMAC_AC01,
|
||||
MT_LMAC_AC02,
|
||||
MT_LMAC_AC03,
|
||||
MT_LMAC_ALTX0 = 0x10,
|
||||
MT_LMAC_BMC0,
|
||||
MT_LMAC_BCN0,
|
||||
MT_LMAC_PSMP0,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_RX_SEL0,
|
||||
MT_RX_SEL1,
|
||||
@ -396,7 +388,7 @@ mt7915_hw_dev(struct ieee80211_hw *hw)
|
||||
static inline struct mt7915_phy *
|
||||
mt7915_ext_phy(struct mt7915_dev *dev)
|
||||
{
|
||||
struct mt76_phy *phy = dev->mt76.phy2;
|
||||
struct mt76_phy *phy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (!phy)
|
||||
return NULL;
|
||||
@ -557,9 +549,10 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask);
|
||||
void mt7915_mac_reset_counters(struct mt7915_phy *phy);
|
||||
void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
|
||||
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
|
||||
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
||||
void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
|
||||
struct ieee80211_key_conf *key, u32 changed);
|
||||
struct ieee80211_key_conf *key,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
void mt7915_mac_set_timing(struct mt7915_phy *phy);
|
||||
int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
@ -579,7 +572,6 @@ int mt7915_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 mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
void mt7915_tx_token_put(struct mt7915_dev *dev);
|
||||
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb);
|
||||
|
@ -305,7 +305,7 @@ enum offs_rev {
|
||||
#define MT_MIB_SDR9_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR9))
|
||||
#define MT_MIB_SDR9_CCA_BUSY_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
#define MT_MIB_SDR10_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR10))
|
||||
#define MT_MIB_SDR10(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR10))
|
||||
#define MT_MIB_SDR10_MRDY_COUNT_MASK GENMASK(25, 0)
|
||||
#define MT_MIB_SDR10_MRDY_COUNT_MASK_MT7916 GENMASK(31, 0)
|
||||
|
||||
@ -329,24 +329,24 @@ enum offs_rev {
|
||||
#define MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK_MT7916 GENMASK(31, 0)
|
||||
|
||||
/* in units of 'us' */
|
||||
#define MT_MIB_SDR16_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR16))
|
||||
#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR16))
|
||||
#define MT_MIB_SDR16_PRIMARY_CCA_BUSY_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
#define MT_MIB_SDR17_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR17))
|
||||
#define MT_MIB_SDR17(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR17))
|
||||
#define MT_MIB_SDR17_SECONDARY_CCA_BUSY_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
#define MT_MIB_SDR18(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR18))
|
||||
#define MT_MIB_SDR18_PRIMARY_ENERGY_DETECT_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
/* units are us */
|
||||
#define MT_MIB_SDR19_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR19))
|
||||
#define MT_MIB_SDR19(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR19))
|
||||
#define MT_MIB_SDR19_CCK_MDRDY_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
#define MT_MIB_SDR20_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR20))
|
||||
#define MT_MIB_SDR20(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR20))
|
||||
#define MT_MIB_SDR20_OFDM_VHT_MDRDY_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
#define MT_MIB_SDR21_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR21))
|
||||
#define MT_MIB_SDR20_GREEN_MDRDY_TIME_MASK GENMASK(23, 0)
|
||||
#define MT_MIB_SDR21(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR21))
|
||||
#define MT_MIB_SDR21_GREEN_MDRDY_TIME_MASK GENMASK(23, 0)
|
||||
|
||||
/* rx ampdu count, 32-bit */
|
||||
#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR22))
|
||||
@ -623,7 +623,7 @@ enum offs_rev {
|
||||
|
||||
/* WFDMA COMMON */
|
||||
#define __RXQ(q) ((q) + __MT_MCUQ_MAX)
|
||||
#define __TXQ(q) (__RXQ(q) + __MT_RXQ_MAX)
|
||||
#define __TXQ(q) (__RXQ(q) + MT_RXQ_BAND2)
|
||||
|
||||
#define MT_Q_ID(q) (dev->q_id[(q)])
|
||||
#define MT_Q_BASE(q) ((dev->wfdma_mask >> (q)) & 0x1 ? \
|
||||
@ -639,7 +639,7 @@ enum offs_rev {
|
||||
|
||||
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
|
||||
MT_MCUQ_ID(q)* 0x4)
|
||||
#define MT_RXQ_EXT_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
|
||||
#define MT_RXQ_BAND1_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
|
||||
MT_RXQ_ID(q)* 0x4)
|
||||
#define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \
|
||||
MT_TXQ_ID(q)* 0x4)
|
||||
@ -671,8 +671,8 @@ enum offs_rev {
|
||||
#define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
|
||||
MT_INT_RX(MT_RXQ_MAIN_WA))
|
||||
|
||||
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_EXT) | \
|
||||
MT_INT_RX(MT_RXQ_EXT_WA) | \
|
||||
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
|
||||
MT_INT_RX(MT_RXQ_BAND1_WA) | \
|
||||
MT_INT_RX(MT_RXQ_MAIN_WA))
|
||||
|
||||
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
|
||||
@ -940,7 +940,7 @@ enum offs_rev {
|
||||
#define MT_ADIE_TYPE_MASK BIT(1)
|
||||
|
||||
/* FW MODE SYNC */
|
||||
#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR)
|
||||
#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR)
|
||||
|
||||
#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)
|
||||
|
||||
|
@ -168,13 +168,14 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min,
|
||||
mt7915_tm_set_wmm_qid(struct mt7915_phy *phy, u8 qid, u8 aifs, u8 cw_min,
|
||||
u16 cw_max, u16 txop)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)phy->monitor_vif->drv_priv;
|
||||
struct mt7915_mcu_tx req = { .total = 1 };
|
||||
struct edca *e = &req.edca[0];
|
||||
|
||||
e->queue = qid;
|
||||
e->queue = qid + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
|
||||
e->set = WMM_PARAM_SET;
|
||||
|
||||
e->aifs = aifs;
|
||||
@ -182,7 +183,7 @@ mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min,
|
||||
e->cw_max = cpu_to_le16(cw_max);
|
||||
e->txop = cpu_to_le16(txop);
|
||||
|
||||
return mt7915_mcu_update_edca(dev, &req);
|
||||
return mt7915_mcu_update_edca(phy->dev, &req);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -244,7 +245,7 @@ done:
|
||||
|
||||
mt7915_tm_set_slot_time(phy, slot_time, sifs);
|
||||
|
||||
return mt7915_tm_set_wmm_qid(dev,
|
||||
return mt7915_tm_set_wmm_qid(phy,
|
||||
mt76_connac_lmac_mapping(IEEE80211_AC_BE),
|
||||
aifsn, cw, cw, 0);
|
||||
}
|
||||
@ -774,7 +775,7 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
|
||||
fcs_err = is_mt7915(&dev->mt76) ? FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) :
|
||||
FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt);
|
||||
|
||||
q = phy->band_idx ? MT_RXQ_EXT : MT_RXQ_MAIN;
|
||||
q = phy->band_idx ? MT_RXQ_BAND1 : MT_RXQ_MAIN;
|
||||
mphy->test.rx_stats.packets[q] += fcs_err;
|
||||
mphy->test.rx_stats.fcs_error[q] += fcs_err;
|
||||
|
||||
|
@ -9,6 +9,7 @@ CFLAGS_trace.o := -I$(src)
|
||||
|
||||
mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o
|
||||
mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
mt7921-common-$(CONFIG_ACPI) += acpi_sar.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
|
||||
|
279
drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c
Normal file
279
drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c
Normal file
@ -0,0 +1,279 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2022 MediaTek Inc. */
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include "mt7921.h"
|
||||
|
||||
static int
|
||||
mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
|
||||
{
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *sar_root, *sar_unit;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
acpi_handle root, handle;
|
||||
acpi_status status;
|
||||
u32 i = 0;
|
||||
|
||||
root = ACPI_HANDLE(mdev->dev);
|
||||
if (!root)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
status = acpi_get_handle(root, method, &handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
status = acpi_evaluate_object(handle, NULL, NULL, &buf);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
sar_root = buf.pointer;
|
||||
if (sar_root->type != ACPI_TYPE_PACKAGE ||
|
||||
sar_root->package.count < 4 ||
|
||||
sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
|
||||
dev_err(mdev->dev, "sar cnt = %d\n",
|
||||
sar_root->package.count);
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (!*tbl) {
|
||||
*tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
|
||||
GFP_KERNEL);
|
||||
if (!*tbl)
|
||||
goto free;
|
||||
}
|
||||
if (len)
|
||||
*len = sar_root->package.count;
|
||||
|
||||
for (i = 0; i < sar_root->package.count; i++) {
|
||||
sar_unit = &sar_root->package.elements[i];
|
||||
|
||||
if (sar_unit->type != ACPI_TYPE_INTEGER)
|
||||
break;
|
||||
*(*tbl + i) = (u8)sar_unit->integer.value;
|
||||
}
|
||||
free:
|
||||
kfree(sar_root);
|
||||
|
||||
return (i == sar_root->package.count) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
/* MTCL : Country List Table for 6G band */
|
||||
static int
|
||||
mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version)
|
||||
{
|
||||
*version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0)
|
||||
? 1 : 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MTDS : Dynamic SAR Power Table */
|
||||
static int
|
||||
mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version)
|
||||
{
|
||||
int len, ret, sarlen, prelen, tblcnt;
|
||||
bool enable;
|
||||
|
||||
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Table content validation */
|
||||
switch (version) {
|
||||
case 1:
|
||||
enable = ((struct mt7921_asar_dyn *)*table)->enable;
|
||||
sarlen = sizeof(struct mt7921_asar_dyn_limit);
|
||||
prelen = sizeof(struct mt7921_asar_dyn);
|
||||
break;
|
||||
case 2:
|
||||
enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable;
|
||||
sarlen = sizeof(struct mt7921_asar_dyn_limit_v2);
|
||||
prelen = sizeof(struct mt7921_asar_dyn_v2);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tblcnt = (len - prelen) / sarlen;
|
||||
if (!enable ||
|
||||
tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN)
|
||||
ret = -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* MTGS : Geo SAR Power Table */
|
||||
static int
|
||||
mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version)
|
||||
{
|
||||
int len, ret = 0, sarlen, prelen, tblcnt;
|
||||
|
||||
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Table content validation */
|
||||
switch (version) {
|
||||
case 1:
|
||||
sarlen = sizeof(struct mt7921_asar_geo_limit);
|
||||
prelen = sizeof(struct mt7921_asar_geo);
|
||||
break;
|
||||
case 2:
|
||||
sarlen = sizeof(struct mt7921_asar_geo_limit_v2);
|
||||
prelen = sizeof(struct mt7921_asar_geo_v2);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tblcnt = (len - prelen) / sarlen;
|
||||
if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO)
|
||||
ret = -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7921_init_acpi_sar(struct mt7921_dev *dev)
|
||||
{
|
||||
struct mt7921_acpi_sar *asar;
|
||||
int ret;
|
||||
|
||||
asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
|
||||
if (!asar)
|
||||
return -ENOMEM;
|
||||
|
||||
mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
|
||||
|
||||
/* MTDS is mandatory. Return error if table is invalid */
|
||||
ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
|
||||
if (ret) {
|
||||
devm_kfree(dev->mt76.dev, asar->dyn);
|
||||
devm_kfree(dev->mt76.dev, asar->countrylist);
|
||||
devm_kfree(dev->mt76.dev, asar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* MTGS is optional */
|
||||
ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
|
||||
if (ret) {
|
||||
devm_kfree(dev->mt76.dev, asar->geo);
|
||||
asar->geo = NULL;
|
||||
}
|
||||
|
||||
dev->phy.acpisar = asar;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s8
|
||||
mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
|
||||
enum nl80211_band band, s8 dyn_power)
|
||||
{
|
||||
struct mt7921_acpi_sar *asar = phy->acpisar;
|
||||
struct mt7921_asar_geo_band *band_pwr;
|
||||
s8 geo_power;
|
||||
u8 idx, max;
|
||||
|
||||
if (!asar->geo)
|
||||
return dyn_power;
|
||||
|
||||
switch (phy->mt76->dev->region) {
|
||||
case NL80211_DFS_FCC:
|
||||
idx = 0;
|
||||
break;
|
||||
case NL80211_DFS_ETSI:
|
||||
idx = 1;
|
||||
break;
|
||||
default: /* WW */
|
||||
idx = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (asar->ver == 1) {
|
||||
band_pwr = &asar->geo->tbl[idx].band[0];
|
||||
max = ARRAY_SIZE(asar->geo->tbl[idx].band);
|
||||
} else {
|
||||
band_pwr = &asar->geo_v2->tbl[idx].band[0];
|
||||
max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
|
||||
}
|
||||
|
||||
switch (band) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
idx = 0;
|
||||
break;
|
||||
case NL80211_BAND_5GHZ:
|
||||
idx = 1;
|
||||
break;
|
||||
case NL80211_BAND_6GHZ:
|
||||
idx = 2;
|
||||
break;
|
||||
default:
|
||||
return dyn_power;
|
||||
}
|
||||
|
||||
if (idx >= max)
|
||||
return dyn_power;
|
||||
|
||||
geo_power = (band_pwr + idx)->pwr;
|
||||
dyn_power += (band_pwr + idx)->offset;
|
||||
|
||||
return min(geo_power, dyn_power);
|
||||
}
|
||||
|
||||
static s8
|
||||
mt7921_asar_range_pwr(struct mt7921_phy *phy,
|
||||
const struct cfg80211_sar_freq_ranges *range,
|
||||
u8 idx)
|
||||
{
|
||||
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
|
||||
struct mt7921_acpi_sar *asar = phy->acpisar;
|
||||
u8 *limit, band, max;
|
||||
|
||||
if (!capa)
|
||||
return 127;
|
||||
|
||||
if (asar->ver == 1) {
|
||||
limit = &asar->dyn->tbl[0].frp[0];
|
||||
max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
|
||||
} else {
|
||||
limit = &asar->dyn_v2->tbl[0].frp[0];
|
||||
max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
|
||||
}
|
||||
|
||||
if (idx >= max)
|
||||
return 127;
|
||||
|
||||
if (range->start_freq >= 5945)
|
||||
band = NL80211_BAND_6GHZ;
|
||||
else if (range->start_freq >= 5150)
|
||||
band = NL80211_BAND_5GHZ;
|
||||
else
|
||||
band = NL80211_BAND_2GHZ;
|
||||
|
||||
return mt7921_asar_get_geo_pwr(phy, band, limit[idx]);
|
||||
}
|
||||
|
||||
int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
|
||||
{
|
||||
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
|
||||
int i;
|
||||
|
||||
if (!phy->acpisar)
|
||||
return 0;
|
||||
|
||||
/* When ACPI SAR enabled in HW, we should apply rules for .frp
|
||||
* 1. w/o .sar_specs : set ACPI SAR power as the defatul value
|
||||
* 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR)
|
||||
*/
|
||||
for (i = 0; i < capa->num_freq_ranges; i++) {
|
||||
struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
|
||||
|
||||
frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
|
||||
if (!frp->range)
|
||||
continue;
|
||||
|
||||
frp->power = min_t(s8, set_default ? 127 : frp->power,
|
||||
mt7921_asar_range_pwr(phy, frp->range, i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
93
drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h
Normal file
93
drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h
Normal file
@ -0,0 +1,93 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2022 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7921_ACPI_SAR_H
|
||||
#define __MT7921_ACPI_SAR_H
|
||||
|
||||
#define MT7921_ASAR_MIN_DYN 1
|
||||
#define MT7921_ASAR_MAX_DYN 8
|
||||
#define MT7921_ASAR_MIN_GEO 3
|
||||
#define MT7921_ASAR_MAX_GEO 8
|
||||
|
||||
#define MT7921_ACPI_MTCL "MTCL"
|
||||
#define MT7921_ACPI_MTDS "MTDS"
|
||||
#define MT7921_ACPI_MTGS "MTGS"
|
||||
|
||||
struct mt7921_asar_dyn_limit {
|
||||
u8 idx;
|
||||
u8 frp[5];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_dyn {
|
||||
u8 names[4];
|
||||
u8 enable;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_dyn_limit tbl[0];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_dyn_limit_v2 {
|
||||
u8 idx;
|
||||
u8 frp[11];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_dyn_v2 {
|
||||
u8 names[4];
|
||||
u8 enable;
|
||||
u8 rsvd;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_dyn_limit_v2 tbl[0];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo_band {
|
||||
u8 pwr;
|
||||
u8 offset;
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo_limit {
|
||||
u8 idx;
|
||||
/* 0:2G, 1:5G */
|
||||
struct mt7921_asar_geo_band band[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo {
|
||||
u8 names[4];
|
||||
u8 version;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_geo_limit tbl[0];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo_limit_v2 {
|
||||
u8 idx;
|
||||
/* 0:2G, 1:5G, 2:6G */
|
||||
struct mt7921_asar_geo_band band[3];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo_v2 {
|
||||
u8 names[4];
|
||||
u8 version;
|
||||
u8 rsvd;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_geo_limit_v2 tbl[0];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_cl {
|
||||
u8 names[4];
|
||||
u8 version;
|
||||
u8 mode_6g;
|
||||
u8 cl6g[6];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_acpi_sar {
|
||||
u8 ver;
|
||||
union {
|
||||
struct mt7921_asar_dyn *dyn;
|
||||
struct mt7921_asar_dyn_v2 *dyn_v2;
|
||||
};
|
||||
union {
|
||||
struct mt7921_asar_geo *geo;
|
||||
struct mt7921_asar_geo_v2 *geo_v2;
|
||||
};
|
||||
struct mt7921_asar_cl *countrylist;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,20 +5,6 @@
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i <= MT_TXQ_PSD; i++)
|
||||
phy->mt76->q_tx[i] = phy->mt76->q_tx[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7921_poll_tx(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct mt7921_dev *dev;
|
||||
@ -31,7 +17,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget)
|
||||
return 0;
|
||||
}
|
||||
|
||||
mt7921_mcu_tx_cleanup(dev);
|
||||
mt76_connac_tx_cleanup(&dev->mt76);
|
||||
if (napi_complete(napi))
|
||||
mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
|
||||
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
|
||||
@ -250,8 +236,9 @@ int mt7921_dma_init(struct mt7921_dev *dev)
|
||||
return ret;
|
||||
|
||||
/* init tx queue */
|
||||
ret = mt7921_init_tx_queues(&dev->phy, MT7921_TXQ_BAND0,
|
||||
MT7921_TX_RING_SIZE);
|
||||
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
|
||||
MT7921_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -34,14 +34,13 @@ mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
|
||||
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
|
||||
dev->mt76.region = request->dfs_region;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt76_connac_mcu_set_channel_domain(hw->priv);
|
||||
mt76_connac_mcu_set_rate_txpower(phy->mt76);
|
||||
mt7921_set_tx_sar_pwr(hw, NULL);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
@ -53,8 +52,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
|
||||
hw->queues = 4;
|
||||
hw->max_rx_aggregation_subframes = 64;
|
||||
hw->max_tx_aggregation_subframes = 128;
|
||||
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
hw->netdev_features = NETIF_F_RXCSUM;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
@ -97,6 +96,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
ieee80211_hw_set(hw, SUPPORTS_PS);
|
||||
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
|
||||
if (dev->pm.enable)
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
@ -289,6 +290,8 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
||||
if (!mt76_is_mmio(&dev->mt76))
|
||||
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
|
||||
mt7921_init_acpi_sar(dev);
|
||||
|
||||
ret = mt7921_init_wcid(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -304,7 +307,7 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
|
||||
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
||||
|
@ -9,10 +9,6 @@
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
|
||||
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
|
||||
IEEE80211_RADIOTAP_HE_##f)
|
||||
|
||||
static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
|
||||
u16 idx, bool unicast)
|
||||
{
|
||||
@ -168,183 +164,6 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll);
|
||||
|
||||
static void
|
||||
mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
||||
struct ieee80211_radiotap_he *he,
|
||||
__le32 *rxv)
|
||||
{
|
||||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
|
||||
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;
|
||||
|
||||
switch (ru) {
|
||||
case 0 ... 36:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
offs = ru;
|
||||
break;
|
||||
case 37 ... 52:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
offs = ru - 37;
|
||||
break;
|
||||
case 53 ... 60:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
offs = ru - 53;
|
||||
break;
|
||||
case 61 ... 64:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
offs = ru - 61;
|
||||
break;
|
||||
case 65 ... 66:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
offs = ru - 65;
|
||||
break;
|
||||
case 67:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
break;
|
||||
case 68:
|
||||
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
|
||||
break;
|
||||
}
|
||||
|
||||
he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
|
||||
le16_encode_bits(offs,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
static const struct ieee80211_radiotap_he_mu mu_known = {
|
||||
.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN) |
|
||||
HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN),
|
||||
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN) |
|
||||
HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN),
|
||||
};
|
||||
struct ieee80211_radiotap_he_mu *he_mu;
|
||||
|
||||
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
|
||||
|
||||
he_mu = skb_push(skb, sizeof(mu_known));
|
||||
memcpy(he_mu, &mu_known, sizeof(mu_known));
|
||||
|
||||
#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
|
||||
|
||||
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
|
||||
if (status->he_dcm)
|
||||
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
|
||||
|
||||
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
|
||||
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
|
||||
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
|
||||
|
||||
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] =
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
|
||||
}
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_80) {
|
||||
he_mu->ru_ch1[1] =
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
|
||||
he_mu->ru_ch2[1] =
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
static const struct ieee80211_radiotap_he known = {
|
||||
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
|
||||
HE_BITS(DATA1_DATA_DCM_KNOWN) |
|
||||
HE_BITS(DATA1_STBC_KNOWN) |
|
||||
HE_BITS(DATA1_CODING_KNOWN) |
|
||||
HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
|
||||
HE_BITS(DATA1_DOPPLER_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
|
||||
HE_BITS(DATA1_BSS_COLOR_KNOWN),
|
||||
.data2 = HE_BITS(DATA2_GI_KNOWN) |
|
||||
HE_BITS(DATA2_TXBF_KNOWN) |
|
||||
HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
|
||||
HE_BITS(DATA2_TXOP_KNOWN),
|
||||
};
|
||||
struct ieee80211_radiotap_he *he = NULL;
|
||||
u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
|
||||
|
||||
status->flag |= RX_FLAG_RADIOTAP_HE;
|
||||
|
||||
he = skb_push(skb, sizeof(known));
|
||||
memcpy(he, &known, sizeof(known));
|
||||
|
||||
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
|
||||
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
|
||||
he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
|
||||
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
|
||||
le16_encode_bits(ltf_size,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
|
||||
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
|
||||
he->data5 |= HE_BITS(DATA5_TXBF);
|
||||
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
|
||||
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
|
||||
|
||||
switch (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_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_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
|
||||
|
||||
mt7921_mac_decode_he_radiotap_ru(status, he, rxv);
|
||||
mt7921_mac_decode_he_mu_radiotap(skb, rxv);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
|
||||
HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
|
||||
|
||||
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]);
|
||||
|
||||
mt7921_mac_decode_he_radiotap_ru(status, he, rxv);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy,
|
||||
struct mt76_rx_status *status, u8 chfreq)
|
||||
@ -399,86 +218,6 @@ mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
mt7921_mac_rssi_iter, skb);
|
||||
}
|
||||
|
||||
/* The HW does not translate the mac header to 802.3 for mesh point */
|
||||
static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap);
|
||||
struct mt7921_sta *msta = (struct mt7921_sta *)status->wcid;
|
||||
__le32 *rxd = (__le32 *)skb->data;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4))
|
||||
return -EINVAL;
|
||||
|
||||
if (!msta || !msta->vif)
|
||||
return -EINVAL;
|
||||
|
||||
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
|
||||
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
|
||||
|
||||
/* store the info from RXD and ethhdr to avoid being overridden */
|
||||
frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL);
|
||||
hdr.frame_control = cpu_to_le16(frame_control);
|
||||
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL));
|
||||
hdr.duration_id = 0;
|
||||
|
||||
ether_addr_copy(hdr.addr1, vif->addr);
|
||||
ether_addr_copy(hdr.addr2, sta->addr);
|
||||
switch (frame_control & (IEEE80211_FCTL_TODS |
|
||||
IEEE80211_FCTL_FROMDS)) {
|
||||
case 0:
|
||||
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
|
||||
break;
|
||||
case IEEE80211_FCTL_FROMDS:
|
||||
ether_addr_copy(hdr.addr3, eth_hdr->h_source);
|
||||
break;
|
||||
case IEEE80211_FCTL_TODS:
|
||||
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
|
||||
break;
|
||||
case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:
|
||||
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
|
||||
ether_addr_copy(hdr.addr4, eth_hdr->h_source);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2);
|
||||
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
|
||||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
|
||||
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
|
||||
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
|
||||
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
|
||||
else
|
||||
skb_pull(skb, 2);
|
||||
|
||||
if (ieee80211_has_order(hdr.frame_control))
|
||||
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9],
|
||||
IEEE80211_HT_CTL_LEN);
|
||||
if (ieee80211_is_data_qos(hdr.frame_control)) {
|
||||
__le16 qos_ctrl;
|
||||
|
||||
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL));
|
||||
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
|
||||
IEEE80211_QOS_CTL_LEN);
|
||||
}
|
||||
|
||||
if (ieee80211_has_a4(hdr.frame_control))
|
||||
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
|
||||
else
|
||||
memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
@ -496,9 +235,10 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
u32 rxd2 = le32_to_cpu(rxd[2]);
|
||||
u32 rxd3 = le32_to_cpu(rxd[3]);
|
||||
u32 rxd4 = le32_to_cpu(rxd[4]);
|
||||
struct mt7921_sta *msta;
|
||||
u16 seq_ctrl = 0;
|
||||
__le16 fc = 0;
|
||||
u32 mode = 0;
|
||||
u8 mode = 0;
|
||||
int i, idx;
|
||||
|
||||
memset(status, 0, sizeof(*status));
|
||||
@ -526,8 +266,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
status->wcid = mt7921_rx_get_wcid(dev, idx, unicast);
|
||||
|
||||
if (status->wcid) {
|
||||
struct mt7921_sta *msta;
|
||||
|
||||
msta = container_of(status->wcid, struct mt7921_sta, wcid);
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
if (list_empty(&msta->poll_list))
|
||||
@ -642,9 +380,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
|
||||
/* RXD Group 3 - P-RXV */
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
|
||||
u8 stbc, gi;
|
||||
u32 v0, v1;
|
||||
bool cck;
|
||||
int ret;
|
||||
|
||||
rxv = rxd;
|
||||
rxd += 2;
|
||||
@ -672,79 +409,10 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
status->chain_signal[i]);
|
||||
}
|
||||
|
||||
stbc = FIELD_GET(MT_PRXV_STBC, v0);
|
||||
gi = FIELD_GET(MT_PRXV_SGI, v0);
|
||||
cck = false;
|
||||
|
||||
idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
|
||||
mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
|
||||
|
||||
switch (mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
i = mt76_get_rate(&dev->mt76, sband, i, cck);
|
||||
break;
|
||||
case MT_PHY_TYPE_HT_GF:
|
||||
case MT_PHY_TYPE_HT:
|
||||
status->encoding = RX_ENC_HT;
|
||||
if (i > 31)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
status->nss =
|
||||
FIELD_GET(MT_PRXV_NSTS, v0) + 1;
|
||||
status->encoding = RX_ENC_VHT;
|
||||
if (i > 11)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
status->nss =
|
||||
FIELD_GET(MT_PRXV_NSTS, v0) + 1;
|
||||
status->encoding = RX_ENC_HE;
|
||||
i &= GENMASK(3, 0);
|
||||
|
||||
if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
|
||||
status->he_gi = gi;
|
||||
|
||||
status->he_dcm = !!(idx & MT_PRXV_TX_DCM);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status->rate_idx = i;
|
||||
|
||||
switch (FIELD_GET(MT_PRXV_FRAME_MODE, v0)) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
if (mode & MT_PHY_TYPE_HE_EXT_SU &&
|
||||
(idx & MT_PRXV_TX_ER_SU_106T)) {
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
status->he_ru =
|
||||
NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
} else {
|
||||
status->bw = RATE_INFO_BW_40;
|
||||
}
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
status->bw = RATE_INFO_BW_80;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
status->bw = RATE_INFO_BW_160;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
|
||||
if (mode < MT_PHY_TYPE_HE_SU && gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, sband,
|
||||
rxv, &mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
|
||||
rxd += 18;
|
||||
@ -762,8 +430,18 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
|
||||
hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
|
||||
if (hdr_trans && ieee80211_has_morefrags(fc)) {
|
||||
if (mt7921_reverse_frag0_hdr_trans(skb, hdr_gap))
|
||||
struct ieee80211_vif *vif;
|
||||
int err;
|
||||
|
||||
if (!msta || !msta->vif)
|
||||
return -EINVAL;
|
||||
|
||||
vif = container_of((void *)msta->vif, struct ieee80211_vif,
|
||||
drv_priv);
|
||||
err = mt76_connac2_reverse_frag0_hdr_trans(vif, skb, hdr_gap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
hdr_trans = false;
|
||||
} else {
|
||||
skb_pull(skb, hdr_gap);
|
||||
@ -796,7 +474,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
mt7921_mac_assoc_rssi(dev, skb);
|
||||
|
||||
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
|
||||
mt7921_mac_decode_he_radiotap(skb, rxv, mode);
|
||||
mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode);
|
||||
|
||||
if (!status->wcid || !ieee80211_is_data_qos(fc))
|
||||
return 0;
|
||||
@ -808,217 +486,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid)
|
||||
{
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u8 fc_type, fc_stype;
|
||||
u16 ethertype;
|
||||
bool wmm = false;
|
||||
u32 val;
|
||||
|
||||
if (wcid->sta) {
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
||||
wmm = sta->wme;
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
|
||||
FIELD_PREP(MT_TXD1_TID, tid);
|
||||
|
||||
ethertype = get_unaligned_be16(&skb->data[12]);
|
||||
if (ethertype >= ETH_P_802_3_MIN)
|
||||
val |= MT_TXD1_ETH_802_3;
|
||||
|
||||
txwi[1] |= cpu_to_le32(val);
|
||||
|
||||
fc_type = IEEE80211_FTYPE_DATA >> 2;
|
||||
fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
|
||||
|
||||
txwi[2] |= cpu_to_le32(val);
|
||||
|
||||
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
||||
txwi[7] |= cpu_to_le32(val);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 fc_type, fc_stype;
|
||||
u32 val;
|
||||
|
||||
if (ieee80211_is_action(fc) &&
|
||||
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
|
||||
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
|
||||
u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
|
||||
|
||||
txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA);
|
||||
tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
} else if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr;
|
||||
u16 control = le16_to_cpu(bar->control);
|
||||
|
||||
tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control);
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
|
||||
FIELD_PREP(MT_TXD1_HDR_INFO,
|
||||
ieee80211_get_hdrlen_from_skb(skb) / 2) |
|
||||
FIELD_PREP(MT_TXD1_TID, tid);
|
||||
txwi[1] |= cpu_to_le32(val);
|
||||
|
||||
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
|
||||
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
|
||||
|
||||
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |
|
||||
FIELD_PREP(MT_TXD2_MULTICAST, multicast);
|
||||
|
||||
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
|
||||
key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
|
||||
val |= MT_TXD2_BIP;
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
|
||||
}
|
||||
|
||||
if (!ieee80211_is_data(fc) || multicast ||
|
||||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
|
||||
val |= MT_TXD2_FIX_RATE;
|
||||
|
||||
txwi[2] |= cpu_to_le32(val);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
||||
u16 seqno = le16_to_cpu(hdr->seq_ctrl);
|
||||
|
||||
if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
struct ieee80211_bar *bar;
|
||||
|
||||
bar = (struct ieee80211_bar *)skb->data;
|
||||
seqno = le16_to_cpu(bar->start_seq_num);
|
||||
}
|
||||
|
||||
val = MT_TXD3_SN_VALID |
|
||||
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
|
||||
txwi[3] |= cpu_to_le32(val);
|
||||
txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
|
||||
}
|
||||
|
||||
if (mt76_is_mmio(&dev->mt76)) {
|
||||
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
||||
txwi[7] |= cpu_to_le32(val);
|
||||
} else {
|
||||
val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
|
||||
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
|
||||
txwi[8] |= cpu_to_le32(val);
|
||||
}
|
||||
}
|
||||
|
||||
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
bool beacon)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt76_phy *mphy = &dev->mphy;
|
||||
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
|
||||
bool is_mmio = mt76_is_mmio(&dev->mt76);
|
||||
u32 sz_txd = is_mmio ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
u16 tx_count = 15;
|
||||
u32 val;
|
||||
|
||||
if (vif) {
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
|
||||
omac_idx = mvif->omac_idx;
|
||||
wmm_idx = mvif->wmm_idx;
|
||||
}
|
||||
|
||||
if (beacon) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_BCN0;
|
||||
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
|
||||
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
|
||||
q_idx = MT_LMAC_ALTX0;
|
||||
} else {
|
||||
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
|
||||
q_idx = wmm_idx * MT7921_MAX_WMM_SETS +
|
||||
mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
|
||||
FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
|
||||
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
|
||||
txwi[0] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
||||
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
||||
|
||||
txwi[1] = cpu_to_le32(val);
|
||||
txwi[2] = 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
|
||||
if (key)
|
||||
val |= MT_TXD3_PROTECT_FRAME;
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
val |= MT_TXD3_NO_ACK;
|
||||
|
||||
txwi[3] = cpu_to_le32(val);
|
||||
txwi[4] = 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD5_PID, pid);
|
||||
if (pid >= MT_PACKET_ID_FIRST)
|
||||
val |= MT_TXD5_TX_STATUS_HOST;
|
||||
txwi[5] = cpu_to_le32(val);
|
||||
|
||||
txwi[6] = 0;
|
||||
txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
|
||||
|
||||
if (is_8023)
|
||||
mt7921_mac_write_txwi_8023(dev, txwi, skb, wcid);
|
||||
else
|
||||
mt7921_mac_write_txwi_80211(dev, txwi, skb, key);
|
||||
|
||||
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
|
||||
int rateidx = vif ? ffs(vif->bss_conf.basic_rates) - 1 : 0;
|
||||
u16 rate, mode;
|
||||
|
||||
/* hardware won't add HTC for mgmt/ctrl frame */
|
||||
txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
|
||||
|
||||
rate = mt76_calculate_default_rate(mphy, rateidx);
|
||||
mode = rate >> 8;
|
||||
rate &= GENMASK(7, 0);
|
||||
rate |= FIELD_PREP(MT_TX_RATE_MODE, mode);
|
||||
|
||||
val = MT_TXD6_FIXED_BW |
|
||||
FIELD_PREP(MT_TXD6_TX_RATE, rate);
|
||||
txwi[6] |= cpu_to_le32(val);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mac_write_txwi);
|
||||
|
||||
void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
{
|
||||
struct mt7921_sta *msta;
|
||||
@ -1044,123 +511,6 @@ void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_tx_check_aggr);
|
||||
|
||||
static bool
|
||||
mt7921_mac_add_txs_skb(struct mt7921_dev *dev, struct mt76_wcid *wcid, int pid,
|
||||
__le32 *txs_data)
|
||||
{
|
||||
struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid);
|
||||
struct mt76_sta_stats *stats = &msta->stats;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct rate_info rate = {};
|
||||
struct sk_buff_head list;
|
||||
u32 txrate, txs, mode;
|
||||
struct sk_buff *skb;
|
||||
bool cck = false;
|
||||
|
||||
mt76_tx_status_lock(mdev, &list);
|
||||
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
info->status.ampdu_len = 1;
|
||||
info->status.ampdu_ack_len = !!(info->flags &
|
||||
IEEE80211_TX_STAT_ACK);
|
||||
|
||||
info->status.rates[0].idx = -1;
|
||||
|
||||
if (!wcid->sta)
|
||||
goto out;
|
||||
|
||||
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
|
||||
|
||||
rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
|
||||
rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
|
||||
|
||||
if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
|
||||
stats->tx_nss[rate.nss - 1]++;
|
||||
if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
|
||||
stats->tx_mcs[rate.mcs]++;
|
||||
|
||||
mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
|
||||
switch (mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &dev->mphy.sband_5g.sband;
|
||||
else
|
||||
sband = &dev->mphy.sband_2g.sband;
|
||||
|
||||
rate.mcs = mt76_get_rate(dev->mphy.dev, sband, rate.mcs, cck);
|
||||
rate.legacy = sband->bitrates[rate.mcs].bitrate;
|
||||
break;
|
||||
case MT_PHY_TYPE_HT:
|
||||
case MT_PHY_TYPE_HT_GF:
|
||||
if (rate.mcs > 31)
|
||||
goto out;
|
||||
|
||||
rate.flags = RATE_INFO_FLAGS_MCS;
|
||||
if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
|
||||
rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
if (rate.mcs > 9)
|
||||
goto out;
|
||||
|
||||
rate.flags = RATE_INFO_FLAGS_VHT_MCS;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
if (rate.mcs > 11)
|
||||
goto out;
|
||||
|
||||
rate.he_gi = wcid->rate.he_gi;
|
||||
rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
|
||||
rate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
stats->tx_mode[mode]++;
|
||||
|
||||
switch (FIELD_GET(MT_TXS0_BW, txs)) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
rate.bw = RATE_INFO_BW_160;
|
||||
stats->tx_bw[3]++;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
rate.bw = RATE_INFO_BW_80;
|
||||
stats->tx_bw[2]++;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
rate.bw = RATE_INFO_BW_40;
|
||||
stats->tx_bw[1]++;
|
||||
break;
|
||||
default:
|
||||
rate.bw = RATE_INFO_BW_20;
|
||||
stats->tx_bw[0]++;
|
||||
break;
|
||||
}
|
||||
wcid->rate = rate;
|
||||
|
||||
out:
|
||||
if (skb)
|
||||
mt76_tx_status_skb_done(mdev, skb, &list);
|
||||
mt76_tx_status_unlock(mdev, &list);
|
||||
|
||||
return !!skb;
|
||||
}
|
||||
|
||||
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
|
||||
{
|
||||
struct mt7921_sta *msta = NULL;
|
||||
@ -1187,12 +537,13 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
mt7921_mac_add_txs_skb(dev, wcid, pid, txs_data);
|
||||
msta = container_of(wcid, struct mt7921_sta, wcid);
|
||||
|
||||
mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data,
|
||||
&msta->stats);
|
||||
if (!wcid->sta)
|
||||
goto out;
|
||||
|
||||
msta = container_of(wcid, struct mt7921_sta, wcid);
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
if (list_empty(&msta->poll_list))
|
||||
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
|
||||
@ -1387,9 +738,9 @@ void mt7921_mac_reset_work(struct work_struct *work)
|
||||
reset_work);
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
dev_err(dev->mt76.dev, "chip reset\n");
|
||||
dev_dbg(dev->mt76.dev, "chip reset\n");
|
||||
dev->hw_full_reset = true;
|
||||
ieee80211_stop_queues(hw);
|
||||
|
||||
@ -1397,11 +748,14 @@ void mt7921_mac_reset_work(struct work_struct *work)
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
for (i = 0; i < 10; i++)
|
||||
if (!mt7921_dev_reset(dev))
|
||||
for (i = 0; i < 10; i++) {
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
ret = mt7921_dev_reset(dev);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip reset failed\n");
|
||||
@ -1538,10 +892,12 @@ void mt7921_pm_wake_work(struct work_struct *work)
|
||||
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
|
||||
mt76_worker_schedule(&mdev->sdio.txrx_worker);
|
||||
} else {
|
||||
local_bh_disable();
|
||||
mt76_for_each_q_rx(mdev, i)
|
||||
napi_schedule(&mdev->napi[i]);
|
||||
local_bh_enable();
|
||||
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
|
||||
mt7921_mcu_tx_cleanup(dev);
|
||||
mt76_connac_tx_cleanup(mdev);
|
||||
}
|
||||
if (test_bit(MT76_STATE_RUNNING, &mphy->state))
|
||||
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
|
||||
@ -1617,7 +973,7 @@ void mt7921_coredump_work(struct work_struct *work)
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
@ -1646,7 +1002,7 @@ mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
|
||||
__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);
|
||||
mt76_connac2_mac_write_txwi(&dev->mt76, txwi, skb, wcid, key, pid, qid, 0);
|
||||
skb_push(skb, MT_SDIO_TXD_SIZE);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#ifndef __MT7921_MAC_H
|
||||
#define __MT7921_MAC_H
|
||||
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
#define MT_CT_PARSE_LEN 72
|
||||
#define MT_CT_DMA_BUF_NUM 2
|
||||
|
||||
@ -27,294 +29,6 @@ enum rx_pkt_type {
|
||||
PKT_TYPE_NORMAL_MCU,
|
||||
};
|
||||
|
||||
/* RXD DW1 */
|
||||
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
|
||||
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
|
||||
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
|
||||
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
|
||||
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
|
||||
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
|
||||
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
|
||||
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
|
||||
#define MT_RXD1_NORMAL_CM BIT(23)
|
||||
#define MT_RXD1_NORMAL_CLM BIT(24)
|
||||
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
|
||||
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
|
||||
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
|
||||
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
|
||||
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
|
||||
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
|
||||
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
|
||||
|
||||
/* RXD DW2 */
|
||||
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
|
||||
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
|
||||
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
|
||||
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
|
||||
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
|
||||
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
|
||||
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
|
||||
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
|
||||
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
|
||||
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
|
||||
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
|
||||
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
|
||||
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
|
||||
#define MT_RXD2_NORMAL_FRAG BIT(27)
|
||||
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
|
||||
#define MT_RXD2_NORMAL_NDATA BIT(29)
|
||||
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
|
||||
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
|
||||
|
||||
/* RXD DW3 */
|
||||
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
|
||||
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
|
||||
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
|
||||
#define MT_RXD3_NORMAL_U2M BIT(0)
|
||||
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
|
||||
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
|
||||
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
|
||||
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
|
||||
#define MT_RXD3_NORMAL_AMSDU BIT(22)
|
||||
#define MT_RXD3_NORMAL_MESH BIT(23)
|
||||
#define MT_RXD3_NORMAL_MHCP BIT(24)
|
||||
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
|
||||
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
|
||||
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
|
||||
#define MT_RXD3_NORMAL_MORE BIT(28)
|
||||
#define MT_RXD3_NORMAL_UNWANT BIT(29)
|
||||
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
|
||||
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
|
||||
|
||||
/* RXD DW4 */
|
||||
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
|
||||
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
|
||||
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
|
||||
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
|
||||
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
|
||||
#define MT_RXD4_NORMAL_CLS BIT(10)
|
||||
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
|
||||
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
|
||||
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
|
||||
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
|
||||
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
|
||||
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
|
||||
|
||||
/* RXD GROUP4 */
|
||||
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
|
||||
#define MT_RXD6_TA_LO GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD7_TA_HI GENMASK(31, 0)
|
||||
|
||||
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
|
||||
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
|
||||
|
||||
/* P-RXV DW0 */
|
||||
#define MT_PRXV_TX_RATE GENMASK(6, 0)
|
||||
#define MT_PRXV_TX_DCM BIT(4)
|
||||
#define MT_PRXV_TX_ER_SU_106T BIT(5)
|
||||
#define MT_PRXV_NSTS GENMASK(9, 7)
|
||||
#define MT_PRXV_TXBF BIT(10)
|
||||
#define MT_PRXV_HT_AD_CODE BIT(11)
|
||||
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
|
||||
#define MT_PRXV_SGI GENMASK(16, 15)
|
||||
#define MT_PRXV_STBC GENMASK(23, 22)
|
||||
#define MT_PRXV_TX_MODE GENMASK(27, 24)
|
||||
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
|
||||
|
||||
/* P-RXV DW1 */
|
||||
#define MT_PRXV_RCPI3 GENMASK(31, 24)
|
||||
#define MT_PRXV_RCPI2 GENMASK(23, 16)
|
||||
#define MT_PRXV_RCPI1 GENMASK(15, 8)
|
||||
#define MT_PRXV_RCPI0 GENMASK(7, 0)
|
||||
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
|
||||
|
||||
/* C-RXV */
|
||||
#define MT_CRXV_HT_STBC GENMASK(1, 0)
|
||||
#define MT_CRXV_TX_MODE GENMASK(7, 4)
|
||||
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
|
||||
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
|
||||
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
|
||||
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
|
||||
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
|
||||
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
|
||||
#define MT_CRXV_HE_UPLINK BIT(31)
|
||||
|
||||
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
|
||||
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
|
||||
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
|
||||
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
|
||||
#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
|
||||
|
||||
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
|
||||
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
|
||||
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
|
||||
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
|
||||
|
||||
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
|
||||
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
|
||||
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
|
||||
#define MT_CRXV_HE_DOPPLER BIT(16)
|
||||
|
||||
#define MT_CRXV_SNR GENMASK(18, 13)
|
||||
#define MT_CRXV_FOE_LO GENMASK(31, 19)
|
||||
#define MT_CRXV_FOE_HI GENMASK(6, 0)
|
||||
#define MT_CRXV_FOE_SHIFT 13
|
||||
|
||||
enum tx_header_format {
|
||||
MT_HDR_FORMAT_802_3,
|
||||
MT_HDR_FORMAT_CMD,
|
||||
MT_HDR_FORMAT_802_11,
|
||||
MT_HDR_FORMAT_802_11_EXT,
|
||||
};
|
||||
|
||||
enum tx_pkt_type {
|
||||
MT_TX_TYPE_CT,
|
||||
MT_TX_TYPE_SF,
|
||||
MT_TX_TYPE_CMD,
|
||||
MT_TX_TYPE_FW,
|
||||
};
|
||||
|
||||
enum tx_port_idx {
|
||||
MT_TX_PORT_IDX_LMAC,
|
||||
MT_TX_PORT_IDX_MCU
|
||||
};
|
||||
|
||||
enum tx_mcu_port_q_idx {
|
||||
MT_TX_MCU_PORT_RX_Q0 = 0x20,
|
||||
MT_TX_MCU_PORT_RX_Q1,
|
||||
MT_TX_MCU_PORT_RX_Q2,
|
||||
MT_TX_MCU_PORT_RX_Q3,
|
||||
MT_TX_MCU_PORT_RX_FWDL = 0x3e
|
||||
};
|
||||
|
||||
#define MT_CT_INFO_APPLY_TXD BIT(0)
|
||||
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
|
||||
#define MT_CT_INFO_MGMT_FRAME BIT(2)
|
||||
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
|
||||
#define MT_CT_INFO_HSR2_TX BIT(4)
|
||||
#define MT_CT_INFO_FROM_HOST BIT(7)
|
||||
|
||||
#define MT_TXD_SIZE (8 * 4)
|
||||
|
||||
#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)
|
||||
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
|
||||
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
|
||||
|
||||
#define MT_TXD1_LONG_FORMAT BIT(31)
|
||||
#define MT_TXD1_TGID BIT(30)
|
||||
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
|
||||
#define MT_TXD1_AMSDU BIT(23)
|
||||
#define MT_TXD1_TID GENMASK(22, 20)
|
||||
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
|
||||
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
|
||||
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
|
||||
#define MT_TXD1_ETH_802_3 BIT(15)
|
||||
#define MT_TXD1_VTA BIT(10)
|
||||
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
|
||||
|
||||
#define MT_TXD2_FIX_RATE BIT(31)
|
||||
#define MT_TXD2_FIXED_RATE BIT(30)
|
||||
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
|
||||
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
|
||||
#define MT_TXD2_FRAG GENMASK(15, 14)
|
||||
#define MT_TXD2_HTC_VLD BIT(13)
|
||||
#define MT_TXD2_DURATION BIT(12)
|
||||
#define MT_TXD2_BIP BIT(11)
|
||||
#define MT_TXD2_MULTICAST BIT(10)
|
||||
#define MT_TXD2_RTS BIT(9)
|
||||
#define MT_TXD2_SOUNDING BIT(8)
|
||||
#define MT_TXD2_NDPA BIT(7)
|
||||
#define MT_TXD2_NDP BIT(6)
|
||||
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
|
||||
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
|
||||
|
||||
#define MT_TXD3_SN_VALID BIT(31)
|
||||
#define MT_TXD3_PN_VALID BIT(30)
|
||||
#define MT_TXD3_SW_POWER_MGMT BIT(29)
|
||||
#define MT_TXD3_BA_DISABLE BIT(28)
|
||||
#define MT_TXD3_SEQ GENMASK(27, 16)
|
||||
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
|
||||
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
|
||||
#define MT_TXD3_TIMING_MEASURE BIT(5)
|
||||
#define MT_TXD3_DAS BIT(4)
|
||||
#define MT_TXD3_EEOSP BIT(3)
|
||||
#define MT_TXD3_EMRD BIT(2)
|
||||
#define MT_TXD3_PROTECT_FRAME BIT(1)
|
||||
#define MT_TXD3_NO_ACK BIT(0)
|
||||
|
||||
#define MT_TXD4_PN_LOW GENMASK(31, 0)
|
||||
|
||||
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
|
||||
#define MT_TXD5_MD BIT(15)
|
||||
#define MT_TXD5_ADD_BA BIT(14)
|
||||
#define MT_TXD5_TX_STATUS_HOST BIT(10)
|
||||
#define MT_TXD5_TX_STATUS_MCU BIT(9)
|
||||
#define MT_TXD5_TX_STATUS_FMT BIT(8)
|
||||
#define MT_TXD5_PID GENMASK(7, 0)
|
||||
|
||||
#define MT_TXD6_TX_IBF BIT(31)
|
||||
#define MT_TXD6_TX_EBF BIT(30)
|
||||
#define MT_TXD6_TX_RATE GENMASK(29, 16)
|
||||
#define MT_TXD6_SGI GENMASK(15, 14)
|
||||
#define MT_TXD6_HELTF GENMASK(13, 12)
|
||||
#define MT_TXD6_LDPC BIT(11)
|
||||
#define MT_TXD6_SPE_ID_IDX BIT(10)
|
||||
#define MT_TXD6_ANT_ID GENMASK(7, 4)
|
||||
#define MT_TXD6_DYN_BW BIT(3)
|
||||
#define MT_TXD6_FIXED_BW BIT(2)
|
||||
#define MT_TXD6_BW GENMASK(1, 0)
|
||||
|
||||
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
|
||||
#define MT_TXD7_UDP_TCP_SUM BIT(29)
|
||||
#define MT_TXD7_IP_SUM BIT(28)
|
||||
|
||||
#define MT_TXD7_TYPE GENMASK(21, 20)
|
||||
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
|
||||
|
||||
#define MT_TXD7_PSE_FID GENMASK(27, 16)
|
||||
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
|
||||
#define MT_TXD7_HW_AMSDU BIT(10)
|
||||
#define MT_TXD7_TX_TIME GENMASK(9, 0)
|
||||
|
||||
#define MT_TXD8_L_TYPE GENMASK(5, 4)
|
||||
#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0)
|
||||
|
||||
#define MT_TX_RATE_STBC BIT(13)
|
||||
#define MT_TX_RATE_NSS GENMASK(12, 10)
|
||||
#define MT_TX_RATE_MODE GENMASK(9, 6)
|
||||
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
|
||||
#define MT_TX_RATE_DCM BIT(4)
|
||||
#define MT_TX_RATE_IDX GENMASK(3, 0)
|
||||
|
||||
#define MT_TXP_MAX_BUF_NUM 6
|
||||
|
||||
struct mt7921_txp {
|
||||
__le16 flags;
|
||||
__le16 token;
|
||||
u8 bss_idx;
|
||||
__le16 rept_wds_wcid;
|
||||
u8 nbuf;
|
||||
__le32 buf[MT_TXP_MAX_BUF_NUM];
|
||||
__le16 len[MT_TXP_MAX_BUF_NUM];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7921_tx_free {
|
||||
__le16 rx_byte_cnt;
|
||||
__le16 ctrl;
|
||||
u8 txd_cnt;
|
||||
u8 rsv[3];
|
||||
__le32 info[];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
|
||||
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
|
||||
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
|
||||
@ -325,56 +39,6 @@ struct mt7921_tx_free {
|
||||
/* will support this field in further revision */
|
||||
#define MT_TX_FREE_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXS0_BW GENMASK(30, 29)
|
||||
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
|
||||
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
|
||||
#define MT_TXS0_TX_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXS2_WCID GENMASK(25, 16)
|
||||
|
||||
#define MT_TXS3_PID GENMASK(31, 24)
|
||||
|
||||
static inline struct mt7921_txp_common *
|
||||
mt7921_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
u8 *txwi;
|
||||
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
txwi = mt76_get_txwi_ptr(dev, t);
|
||||
|
||||
return (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE);
|
||||
}
|
||||
|
||||
#define MT_HW_TXP_MAX_MSDU_NUM 4
|
||||
#define MT_HW_TXP_MAX_BUF_NUM 4
|
||||
|
||||
#define MT_MSDU_ID_VALID BIT(15)
|
||||
|
||||
#define MT_TXD_LEN_MASK GENMASK(11, 0)
|
||||
#define MT_TXD_LEN_MSDU_LAST BIT(14)
|
||||
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
|
||||
#define MT_TXD_LEN_LAST BIT(15)
|
||||
|
||||
struct mt7921_txp_ptr {
|
||||
__le32 buf0;
|
||||
__le16 len0;
|
||||
__le16 len1;
|
||||
__le32 buf1;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7921_hw_txp {
|
||||
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
|
||||
struct mt7921_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7921_txp_common {
|
||||
union {
|
||||
struct mt7921_hw_txp hw;
|
||||
};
|
||||
};
|
||||
|
||||
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
|
||||
#define MT_WTBL_TXRX_RATE_G2_HE 24
|
||||
#define MT_WTBL_TXRX_RATE_G2 12
|
||||
|
@ -257,7 +257,7 @@ int __mt7921_start(struct mt7921_phy *phy)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt76_connac_mcu_set_rate_txpower(phy->mt76);
|
||||
err = mt7921_set_tx_sar_pwr(mphy->hw, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -322,7 +322,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
mvif->mt76.omac_idx = mvif->mt76.idx;
|
||||
mvif->phy = phy;
|
||||
mvif->mt76.band_idx = 0;
|
||||
mvif->mt76.wmm_idx = mvif->mt76.idx % MT7921_MAX_WMM_SETS;
|
||||
mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
|
||||
|
||||
ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid,
|
||||
true);
|
||||
@ -336,7 +336,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
INIT_LIST_HEAD(&mvif->sta.poll_list);
|
||||
mvif->sta.wcid.idx = idx;
|
||||
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
@ -352,6 +352,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
out:
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
@ -495,8 +496,21 @@ static void
|
||||
mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_dev *dev = priv;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
bool pm_enable = dev->pm.enable;
|
||||
int err;
|
||||
|
||||
mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable);
|
||||
err = mt7921_mcu_set_beacon_filter(dev, vif, pm_enable);
|
||||
if (err < 0)
|
||||
return;
|
||||
|
||||
if (pm_enable) {
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
} else {
|
||||
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
|
||||
__clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -548,7 +562,7 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
ret = mt76_connac_mcu_set_rate_txpower(phy->mt76);
|
||||
ret = mt7921_set_tx_sar_pwr(hw, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@ -654,15 +668,6 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
|
||||
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
|
||||
true);
|
||||
mt7921_mcu_sta_update(dev, NULL, vif, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
}
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7921_mcu_uni_add_beacon_offload(dev, hw, vif,
|
||||
@ -678,8 +683,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
mt7921_mcu_sta_update(dev, NULL, vif, true,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
if (dev->pm.enable)
|
||||
mt7921_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
|
||||
mt7921_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ARP_FILTER) {
|
||||
@ -708,7 +712,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
msta->vif = mvif;
|
||||
msta->wcid.sta = 1;
|
||||
msta->wcid.idx = idx;
|
||||
msta->wcid.ext_phy = mvif->mt76.band_idx;
|
||||
msta->wcid.phy_idx = mvif->mt76.band_idx;
|
||||
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
msta->last_txs = jiffies;
|
||||
|
||||
@ -1178,7 +1182,7 @@ void mt7921_scan_work(struct work_struct *work)
|
||||
scan_work.work);
|
||||
|
||||
while (true) {
|
||||
struct mt7921_mcu_rxd *rxd;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
struct sk_buff *skb;
|
||||
|
||||
spin_lock_bh(&phy->dev->mt76.lock);
|
||||
@ -1188,7 +1192,7 @@ void mt7921_scan_work(struct work_struct *work)
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
rxd = (struct mt7921_mcu_rxd *)skb->data;
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
if (rxd->eid == MCU_EVENT_SCHED_SCAN_DONE) {
|
||||
ieee80211_sched_scan_results(phy->mt76->hw);
|
||||
} else if (test_and_clear_bit(MT76_HW_SCANNING,
|
||||
@ -1451,15 +1455,14 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
if (!idx)
|
||||
return;
|
||||
|
||||
skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) +
|
||||
idx * sizeof(struct in6_addr), GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
req_hdr.arpns.ips_num = idx;
|
||||
req_hdr.arpns.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)
|
||||
+ idx * sizeof(struct in6_addr));
|
||||
skb_put_data(skb, &req_hdr, sizeof(req_hdr));
|
||||
skb = __mt76_mcu_msg_alloc(&dev->mt76, &req_hdr,
|
||||
sizeof(req_hdr) + idx * sizeof(struct in6_addr),
|
||||
sizeof(req_hdr), GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
for (i = 0; i < idx; i++)
|
||||
skb_put_data(skb, &ns_addrs[i].in6_u, sizeof(struct in6_addr));
|
||||
@ -1470,20 +1473,33 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
}
|
||||
#endif
|
||||
|
||||
int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar)
|
||||
{
|
||||
struct mt76_phy *mphy = hw->priv;
|
||||
int err;
|
||||
|
||||
if (sar) {
|
||||
err = mt76_init_sar_power(hw, sar);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
mt7921_init_acpi_sar_power(mt7921_hw_phy(hw), !sar);
|
||||
|
||||
err = mt76_connac_mcu_set_rate_txpower(mphy);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7921_set_sar_specs(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt76_phy *mphy = hw->priv;
|
||||
int err;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
err = mt76_init_sar_power(hw, sar);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt76_connac_mcu_set_rate_txpower(mphy);
|
||||
out:
|
||||
err = mt7921_set_tx_sar_pwr(hw, sar);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return err;
|
||||
@ -1501,6 +1517,44 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw,
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
int err;
|
||||
|
||||
err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
|
||||
true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt7921_mcu_set_bss_pm(dev, vif, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mt7921_mcu_sta_update(dev, NULL, vif, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
int err;
|
||||
|
||||
err = mt7921_mcu_set_bss_pm(dev, vif, false);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7921_ops = {
|
||||
.tx = mt7921_tx,
|
||||
.start = mt7921_start,
|
||||
@ -1511,6 +1565,8 @@ const struct ieee80211_ops mt7921_ops = {
|
||||
.conf_tx = mt7921_conf_tx,
|
||||
.configure_filter = mt7921_configure_filter,
|
||||
.bss_info_changed = mt7921_bss_info_changed,
|
||||
.start_ap = mt7921_start_ap,
|
||||
.stop_ap = mt7921_stop_ap,
|
||||
.sta_state = mt7921_sta_state,
|
||||
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
|
||||
.set_key = mt7921_set_key,
|
||||
|
@ -1,79 +1,15 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/fs.h>
|
||||
#include "mt7921.h"
|
||||
#include "mt7921_trace.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
struct mt7921_patch_hdr {
|
||||
char build_date[16];
|
||||
char platform[4];
|
||||
__be32 hw_sw_ver;
|
||||
__be32 patch_ver;
|
||||
__be16 checksum;
|
||||
u16 reserved;
|
||||
struct {
|
||||
__be32 patch_ver;
|
||||
__be32 subsys;
|
||||
__be32 feature;
|
||||
__be32 n_region;
|
||||
__be32 crc;
|
||||
u32 reserved[11];
|
||||
} desc;
|
||||
} __packed;
|
||||
|
||||
struct mt7921_patch_sec {
|
||||
__be32 type;
|
||||
__be32 offs;
|
||||
__be32 size;
|
||||
union {
|
||||
__be32 spec[13];
|
||||
struct {
|
||||
__be32 addr;
|
||||
__be32 len;
|
||||
__be32 sec_key_idx;
|
||||
__be32 align_len;
|
||||
u32 reserved[9];
|
||||
} info;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct mt7921_fw_trailer {
|
||||
u8 chip_id;
|
||||
u8 eco_code;
|
||||
u8 n_region;
|
||||
u8 format_ver;
|
||||
u8 format_flag;
|
||||
u8 reserved[2];
|
||||
char fw_ver[10];
|
||||
char build_date[15];
|
||||
u32 crc;
|
||||
} __packed;
|
||||
|
||||
struct mt7921_fw_region {
|
||||
__le32 decomp_crc;
|
||||
__le32 decomp_len;
|
||||
__le32 decomp_blk_sz;
|
||||
u8 reserved[4];
|
||||
__le32 addr;
|
||||
__le32 len;
|
||||
u8 feature_set;
|
||||
u8 reserved1[15];
|
||||
} __packed;
|
||||
|
||||
#define MT_STA_BFER BIT(0)
|
||||
#define MT_STA_BFEE BIT(1)
|
||||
|
||||
#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24)
|
||||
#define PATCH_SEC_ENC_TYPE_PLAIN 0x00
|
||||
#define PATCH_SEC_ENC_TYPE_AES 0x01
|
||||
#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02
|
||||
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
|
||||
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
|
||||
|
||||
static int
|
||||
mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
@ -83,7 +19,7 @@ mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
|
||||
res = (struct mt7921_mcu_eeprom_info *)skb->data;
|
||||
buf = dev->eeprom.data + le32_to_cpu(res->addr);
|
||||
@ -96,7 +32,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
struct sk_buff *skb, int seq)
|
||||
{
|
||||
int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
|
||||
struct mt7921_mcu_rxd *rxd;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
int ret = 0;
|
||||
|
||||
if (!skb) {
|
||||
@ -107,11 +43,12 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
rxd = (struct mt7921_mcu_rxd *)skb->data;
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
if (seq != rxd->seq)
|
||||
return -EAGAIN;
|
||||
|
||||
if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
|
||||
if (cmd == MCU_CMD(PATCH_SEM_CONTROL) ||
|
||||
cmd == MCU_CMD(PATCH_FINISH_REQ)) {
|
||||
skb_pull(skb, sizeof(*rxd) - 4);
|
||||
ret = *skb->data;
|
||||
} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
|
||||
@ -140,90 +77,13 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
event = (struct mt7921_mcu_reg_event *)skb->data;
|
||||
ret = (int)le32_to_cpu(event->val);
|
||||
} else {
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response);
|
||||
|
||||
int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
|
||||
struct mt7921_uni_txd *uni_txd;
|
||||
struct mt7921_mcu_txd *mcu_txd;
|
||||
__le32 *txd;
|
||||
u32 val;
|
||||
u8 seq;
|
||||
|
||||
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(SUSPEND) ||
|
||||
cmd == MCU_UNI_CMD(OFFLOAD))
|
||||
mdev->mcu.timeout = HZ;
|
||||
else
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
|
||||
seq = ++dev->mt76.mcu.msg_seq & 0xf;
|
||||
if (!seq)
|
||||
seq = ++dev->mt76.mcu.msg_seq & 0xf;
|
||||
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
goto exit;
|
||||
|
||||
txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);
|
||||
txd = (__le32 *)skb_push(skb, txd_len);
|
||||
|
||||
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
|
||||
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |
|
||||
FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);
|
||||
txd[0] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);
|
||||
txd[1] = cpu_to_le32(val);
|
||||
|
||||
if (cmd & __MCU_CMD_FIELD_UNI) {
|
||||
uni_txd = (struct mt7921_uni_txd *)txd;
|
||||
uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));
|
||||
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
|
||||
uni_txd->cid = cpu_to_le16(mcu_cmd);
|
||||
uni_txd->s2d_index = MCU_S2D_H2N;
|
||||
uni_txd->pkt_type = MCU_PKT_ID;
|
||||
uni_txd->seq = seq;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mcu_txd = (struct mt7921_mcu_txd *)txd;
|
||||
mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
|
||||
mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,
|
||||
MT_TX_MCU_PORT_RX_Q0));
|
||||
mcu_txd->pkt_type = MCU_PKT_ID;
|
||||
mcu_txd->seq = seq;
|
||||
mcu_txd->cid = mcu_cmd;
|
||||
mcu_txd->s2d_index = MCU_S2D_H2N;
|
||||
mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
|
||||
|
||||
if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {
|
||||
if (cmd & __MCU_CMD_FIELD_QUERY)
|
||||
mcu_txd->set_query = MCU_Q_QUERY;
|
||||
else
|
||||
mcu_txd->set_query = MCU_Q_SET;
|
||||
mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;
|
||||
} else {
|
||||
mcu_txd->set_query = MCU_Q_NA;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (wait_seq)
|
||||
*wait_seq = seq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mcu_fill_message);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int
|
||||
@ -304,7 +164,7 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
struct mt76_connac_beacon_loss_event *event;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
event = (struct mt76_connac_beacon_loss_event *)skb->data;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
|
||||
@ -318,7 +178,7 @@ mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt76_connac_mcu_bss_event *event;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
event = (struct mt76_connac_mcu_bss_event *)skb->data;
|
||||
if (event->is_absent)
|
||||
ieee80211_stop_queues(mphy->hw);
|
||||
@ -338,7 +198,7 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
u8 content[512];
|
||||
} __packed * msg;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
msg = (struct mt7921_debug_msg *)skb->data;
|
||||
|
||||
if (msg->type == 3) { /* fw log */
|
||||
@ -361,7 +221,7 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
u8 reserved[3];
|
||||
} __packed * event;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
event = (struct mt7921_mcu_lp_event *)skb->data;
|
||||
|
||||
trace_lp_event(dev, event->state);
|
||||
@ -372,7 +232,7 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_mcu_tx_done_event *event;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
event = (struct mt7921_mcu_tx_done_event *)skb->data;
|
||||
|
||||
mt7921_mac_add_txs(dev, event->txs);
|
||||
@ -381,8 +241,9 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
static void
|
||||
mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
switch (rxd->eid) {
|
||||
case MCU_EVENT_BSS_BEACON_LOSS:
|
||||
mt7921_mcu_connection_loss_event(dev, skb);
|
||||
@ -416,12 +277,12 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
|
||||
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_mcu_rxd *rxd;
|
||||
struct mt76_connac2_mcu_rxd *rxd;
|
||||
|
||||
if (skb_linearize(skb))
|
||||
return;
|
||||
|
||||
rxd = (struct mt7921_mcu_rxd *)skb->data;
|
||||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
|
||||
if (rxd->eid == 0x6) {
|
||||
mt76_mcu_rx_event(&dev->mt76, skb);
|
||||
@ -469,34 +330,6 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
|
||||
enable, false);
|
||||
}
|
||||
|
||||
static u32 mt7921_get_data_mode(struct mt7921_dev *dev, u32 info)
|
||||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if (info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
case PATCH_SEC_ENC_TYPE_PLAIN:
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_AES:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_SCRAMBLE:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= DL_CONFIG_ENCRY_MODE_SEL;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Encryption type not support!\n");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static char *mt7921_patch_name(struct mt7921_dev *dev)
|
||||
{
|
||||
char *ret;
|
||||
@ -509,152 +342,6 @@ static char *mt7921_patch_name(struct mt7921_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7921_load_patch(struct mt7921_dev *dev)
|
||||
{
|
||||
const struct mt7921_patch_hdr *hdr;
|
||||
const struct firmware *fw = NULL;
|
||||
int i, ret, sem, max_len;
|
||||
|
||||
max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;
|
||||
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);
|
||||
switch (sem) {
|
||||
case PATCH_IS_DL:
|
||||
return 0;
|
||||
case PATCH_NOT_DL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, mt7921_patch_name(dev), dev->mt76.dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt7921_patch_hdr *)(fw->data);
|
||||
|
||||
dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
|
||||
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
|
||||
|
||||
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
|
||||
struct mt7921_patch_sec *sec;
|
||||
const u8 *dl;
|
||||
u32 len, addr, mode;
|
||||
u32 sec_info = 0;
|
||||
|
||||
sec = (struct mt7921_patch_sec *)(fw->data + sizeof(*hdr) +
|
||||
i * sizeof(*sec));
|
||||
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
|
||||
PATCH_SEC_TYPE_INFO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = be32_to_cpu(sec->info.addr);
|
||||
len = be32_to_cpu(sec->info.len);
|
||||
dl = fw->data + be32_to_cpu(sec->offs);
|
||||
sec_info = be32_to_cpu(sec->info.sec_key_idx);
|
||||
mode = mt7921_get_data_mode(dev, sec_info);
|
||||
|
||||
ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
|
||||
mode);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Download request failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
|
||||
dl, len, max_len);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to send patch\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_start_patch(&dev->mt76);
|
||||
if (ret)
|
||||
dev_err(dev->mt76.dev, "Failed to start patch\n");
|
||||
|
||||
if (mt76_is_sdio(&dev->mt76)) {
|
||||
/* activate again */
|
||||
ret = __mt7921_mcu_fw_pmctrl(dev);
|
||||
if (!ret)
|
||||
ret = __mt7921_mcu_drv_pmctrl(dev);
|
||||
}
|
||||
|
||||
out:
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
|
||||
switch (sem) {
|
||||
case PATCH_REL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ret = -EAGAIN;
|
||||
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
|
||||
break;
|
||||
}
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_mcu_send_ram_firmware(struct mt7921_dev *dev,
|
||||
const struct mt7921_fw_trailer *hdr,
|
||||
const u8 *data, bool is_wa)
|
||||
{
|
||||
int i, offset = 0, max_len;
|
||||
u32 override = 0, option = 0;
|
||||
|
||||
max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;
|
||||
|
||||
for (i = 0; i < hdr->n_region; i++) {
|
||||
const struct mt7921_fw_region *region;
|
||||
int err;
|
||||
u32 len, addr, mode;
|
||||
|
||||
region = (const struct mt7921_fw_region *)((const u8 *)hdr -
|
||||
(hdr->n_region - i) * sizeof(*region));
|
||||
mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
|
||||
region->feature_set, is_wa);
|
||||
len = le32_to_cpu(region->len);
|
||||
addr = le32_to_cpu(region->addr);
|
||||
|
||||
if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
|
||||
override = addr;
|
||||
|
||||
err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
|
||||
mode);
|
||||
if (err) {
|
||||
dev_err(dev->mt76.dev, "Download request failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
|
||||
data + offset, len, max_len);
|
||||
if (err) {
|
||||
dev_err(dev->mt76.dev, "Failed to send firmware.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
if (override)
|
||||
option |= FW_START_OVERRIDE;
|
||||
|
||||
if (is_wa)
|
||||
option |= FW_START_WORKING_PDA_CR4;
|
||||
|
||||
return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
|
||||
}
|
||||
|
||||
static char *mt7921_ram_name(struct mt7921_dev *dev)
|
||||
{
|
||||
char *ret;
|
||||
@ -667,44 +354,6 @@ static char *mt7921_ram_name(struct mt7921_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7921_load_ram(struct mt7921_dev *dev)
|
||||
{
|
||||
const struct mt7921_fw_trailer *hdr;
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, mt7921_ram_name(dev), dev->mt76.dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt7921_fw_trailer *)(fw->data + fw->size -
|
||||
sizeof(*hdr));
|
||||
|
||||
dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
|
||||
hdr->fw_ver, hdr->build_date);
|
||||
|
||||
ret = mt7921_mcu_send_ram_firmware(dev, hdr, fw->data, false);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(dev->mt76.hw->wiphy->fw_version,
|
||||
sizeof(dev->mt76.hw->wiphy->fw_version),
|
||||
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7921_load_firmware(struct mt7921_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -715,11 +364,18 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
|
||||
goto fw_loaded;
|
||||
}
|
||||
|
||||
ret = mt7921_load_patch(dev);
|
||||
ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7921_load_ram(dev);
|
||||
if (mt76_is_sdio(&dev->mt76)) {
|
||||
/* activate again */
|
||||
ret = __mt7921_mcu_fw_pmctrl(dev);
|
||||
if (!ret)
|
||||
ret = __mt7921_mcu_drv_pmctrl(dev);
|
||||
}
|
||||
|
||||
ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -771,12 +427,6 @@ int mt7921_run_firmware(struct mt7921_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_run_firmware);
|
||||
|
||||
void mt7921_mcu_exit(struct mt7921_dev *dev)
|
||||
{
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mcu_exit);
|
||||
|
||||
int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
@ -1019,7 +669,7 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
&bcnft_req, sizeof(bcnft_req), true);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
@ -1048,9 +698,6 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
};
|
||||
int err;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return 0;
|
||||
|
||||
err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),
|
||||
&req_hdr, sizeof(req_hdr), false);
|
||||
if (err < 0 || !enable)
|
||||
@ -1132,7 +779,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
int err;
|
||||
|
||||
if (enable) {
|
||||
@ -1140,8 +786,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
|
||||
return 0;
|
||||
@ -1151,8 +795,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
|
||||
__clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags);
|
||||
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
|
||||
return 0;
|
||||
@ -1255,8 +897,11 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* support enable/update process only
|
||||
* disable flow would be handled in bss stop handler automatically
|
||||
*/
|
||||
if (!enable)
|
||||
goto out;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);
|
||||
if (!skb)
|
||||
@ -1268,8 +913,8 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mt7921_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
|
||||
wcid, NULL, 0, true);
|
||||
mt76_connac2_mac_write_txwi(&dev->mt76, (__le32 *)(req.beacon_tlv.pkt),
|
||||
skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON);
|
||||
memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
|
||||
req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
|
||||
@ -1282,7 +927,6 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
out:
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
@ -6,76 +6,6 @@
|
||||
|
||||
#include "../mt76_connac_mcu.h"
|
||||
|
||||
struct mt7921_mcu_txd {
|
||||
__le32 txd[8];
|
||||
|
||||
__le16 len;
|
||||
__le16 pq_id;
|
||||
|
||||
u8 cid;
|
||||
u8 pkt_type;
|
||||
u8 set_query; /* FW don't care */
|
||||
u8 seq;
|
||||
|
||||
u8 uc_d2b0_rev;
|
||||
u8 ext_cid;
|
||||
u8 s2d_index;
|
||||
u8 ext_cid_ack;
|
||||
|
||||
u32 reserved[5];
|
||||
} __packed __aligned(4);
|
||||
|
||||
/**
|
||||
* struct mt7921_uni_txd - mcu command descriptor for firmware v3
|
||||
* @txd: hardware descriptor
|
||||
* @len: total length not including txd
|
||||
* @cid: command identifier
|
||||
* @pkt_type: must be 0xa0 (cmd packet by long format)
|
||||
* @frag_n: fragment number
|
||||
* @seq: sequence number
|
||||
* @checksum: 0 mean there is no checksum
|
||||
* @s2d_index: index for command source and destination
|
||||
* Definition | value | note
|
||||
* CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM
|
||||
* CMD_S2D_IDX_C2N | 0x01 | command from WA to WM
|
||||
* CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA
|
||||
* CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM
|
||||
*
|
||||
* @option: command option
|
||||
* BIT[0]: UNI_CMD_OPT_BIT_ACK
|
||||
* set to 1 to request a fw reply
|
||||
* if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY
|
||||
* is set, mcu firmware will send response event EID = 0x01
|
||||
* (UNI_EVENT_ID_CMD_RESULT) to the host.
|
||||
* BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD
|
||||
* 0: original command
|
||||
* 1: unified command
|
||||
* BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY
|
||||
* 0: QUERY command
|
||||
* 1: SET command
|
||||
*/
|
||||
struct mt7921_uni_txd {
|
||||
__le32 txd[8];
|
||||
|
||||
/* DW1 */
|
||||
__le16 len;
|
||||
__le16 cid;
|
||||
|
||||
/* DW2 */
|
||||
u8 reserved;
|
||||
u8 pkt_type;
|
||||
u8 frag_n;
|
||||
u8 seq;
|
||||
|
||||
/* DW3 */
|
||||
__le16 checksum;
|
||||
u8 s2d_index;
|
||||
u8 option;
|
||||
|
||||
/* DW4 */
|
||||
u8 reserved2[4];
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mt7921_mcu_tx_done_event {
|
||||
u8 pid;
|
||||
u8 status;
|
||||
@ -108,21 +38,6 @@ enum {
|
||||
MCU_EXT_EVENT_RATE_REPORT = 0x87,
|
||||
};
|
||||
|
||||
struct mt7921_mcu_rxd {
|
||||
__le32 rxd[6];
|
||||
|
||||
__le16 len;
|
||||
__le16 pkt_type_id;
|
||||
|
||||
u8 eid;
|
||||
u8 seq;
|
||||
__le16 __rsv;
|
||||
|
||||
u8 ext_eid;
|
||||
u8 __rsv1[2];
|
||||
u8 s2d_index;
|
||||
};
|
||||
|
||||
struct mt7921_mcu_eeprom_info {
|
||||
__le32 addr;
|
||||
__le32 valid;
|
||||
@ -135,9 +50,6 @@ struct mt7921_mcu_eeprom_info {
|
||||
#define MT_RA_RATE_DCM_EN BIT(4)
|
||||
#define MT_RA_RATE_BW GENMASK(14, 13)
|
||||
|
||||
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
|
||||
#define MCU_PKT_ID 0xa0
|
||||
|
||||
struct mt7921_mcu_uni_event {
|
||||
u8 cid;
|
||||
u8 pad[3];
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include <linux/ktime.h>
|
||||
#include "../mt76_connac_mcu.h"
|
||||
#include "regs.h"
|
||||
#include "acpi_sar.h"
|
||||
|
||||
#define MT7921_MAX_INTERFACES 4
|
||||
#define MT7921_MAX_WMM_SETS 4
|
||||
#define MT7921_WTBL_SIZE 20
|
||||
#define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1)
|
||||
#define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \
|
||||
@ -171,6 +171,9 @@ struct mt7921_phy {
|
||||
|
||||
struct sk_buff_head scan_event_list;
|
||||
struct delayed_work scan_work;
|
||||
#ifdef CONFIG_ACPI
|
||||
struct mt7921_acpi_sar *acpisar;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
|
||||
@ -247,16 +250,6 @@ struct mt7921_txpwr {
|
||||
} data[TXPWR_MAX_NUM];
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_LMAC_AC00,
|
||||
MT_LMAC_AC01,
|
||||
MT_LMAC_AC02,
|
||||
MT_LMAC_AC03,
|
||||
MT_LMAC_ALTX0 = 0x10,
|
||||
MT_LMAC_BMC0,
|
||||
MT_LMAC_BCN0,
|
||||
};
|
||||
|
||||
static inline struct mt7921_phy *
|
||||
mt7921_hw_phy(struct ieee80211_hw *hw)
|
||||
{
|
||||
@ -279,7 +272,6 @@ mt7921_hw_dev(struct ieee80211_hw *hw)
|
||||
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
|
||||
|
||||
extern const struct ieee80211_ops mt7921_ops;
|
||||
extern struct pci_driver mt7921_pci_driver;
|
||||
|
||||
u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
|
||||
|
||||
@ -291,6 +283,8 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force);
|
||||
int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev);
|
||||
void mt7921_dma_cleanup(struct mt7921_dev *dev);
|
||||
int mt7921_run_firmware(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif, bool enable,
|
||||
enum mt76_sta_info_state state);
|
||||
@ -301,7 +295,6 @@ int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct rate_info *rate);
|
||||
int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl);
|
||||
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
|
||||
void mt7921_mcu_exit(struct mt7921_dev *dev);
|
||||
|
||||
static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask)
|
||||
{
|
||||
@ -352,12 +345,6 @@ static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev)
|
||||
return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
}
|
||||
|
||||
static inline void mt7921_mcu_tx_cleanup(struct mt7921_dev *dev)
|
||||
{
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb,
|
||||
int type)
|
||||
@ -392,7 +379,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
struct mt76_tx_info *tx_info);
|
||||
|
||||
void mt7921_tx_worker(struct mt76_worker *w);
|
||||
void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
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);
|
||||
@ -424,14 +410,8 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
void *data, int len);
|
||||
int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
|
||||
struct netlink_callback *cb, void *data, int len);
|
||||
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
bool beacon);
|
||||
void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi);
|
||||
void mt7921_mac_sta_poll(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq);
|
||||
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
struct sk_buff *skb, int seq);
|
||||
|
||||
@ -481,4 +461,22 @@ int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
#ifdef CONFIG_ACPI
|
||||
int mt7921_init_acpi_sar(struct mt7921_dev *dev);
|
||||
int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default);
|
||||
#else
|
||||
static inline int
|
||||
mt7921_init_acpi_sar(struct mt7921_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar);
|
||||
#endif
|
||||
|
@ -116,7 +116,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
|
||||
mt7921_mcu_drv_pmctrl(dev);
|
||||
mt7921_dma_cleanup(dev);
|
||||
mt7921_wfsys_reset(dev);
|
||||
mt7921_mcu_exit(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
}
|
||||
@ -230,14 +230,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
/* txwi_size = txd size + txp size */
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7921_txp_common),
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
|
||||
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.token_size = MT7921_TOKEN_SIZE,
|
||||
.tx_prepare_skb = mt7921e_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921e_tx_complete_skb,
|
||||
.tx_complete_skb = mt76_connac_tx_complete_skb,
|
||||
.rx_check = mt7921e_rx_check,
|
||||
.rx_skb = mt7921e_queue_rx_skb,
|
||||
.rx_poll_complete = mt7921_rx_poll_complete,
|
||||
@ -247,7 +247,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
.sta_remove = mt7921_mac_sta_remove,
|
||||
.update_survey = mt7921_update_channel,
|
||||
};
|
||||
|
||||
static const struct mt7921_hif_ops mt7921_pcie_ops = {
|
||||
.init_reset = mt7921e_init_reset,
|
||||
.reset = mt7921e_mac_reset,
|
||||
@ -359,9 +358,9 @@ static void mt7921_pci_remove(struct pci_dev *pdev)
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int mt7921_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
@ -391,8 +390,6 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
napi_disable(&mdev->napi[i]);
|
||||
}
|
||||
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
|
||||
|
||||
/* wait until dma is idle */
|
||||
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
|
||||
@ -412,8 +409,6 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
if (err)
|
||||
goto restore_napi;
|
||||
|
||||
pci_save_state(pdev);
|
||||
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
if (err)
|
||||
goto restore_napi;
|
||||
|
||||
@ -436,19 +431,14 @@ restore_suspend:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7921_pci_resume(struct pci_dev *pdev)
|
||||
static int mt7921_pci_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int i, err;
|
||||
|
||||
err = pci_set_power_state(pdev, PCI_D0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pci_restore_state(pdev);
|
||||
|
||||
err = mt7921_mcu_drv_pmctrl(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -488,17 +478,15 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
struct pci_driver mt7921_pci_driver = {
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume);
|
||||
|
||||
static struct pci_driver mt7921_pci_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = mt7921_pci_device_table,
|
||||
.probe = mt7921_pci_probe,
|
||||
.remove = mt7921_pci_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mt7921_pci_suspend,
|
||||
.resume = mt7921_pci_resume,
|
||||
#endif /* CONFIG_PM */
|
||||
.driver.pm = pm_sleep_ptr(&mt7921_pm_ops),
|
||||
};
|
||||
|
||||
module_pci_driver(mt7921_pci_driver);
|
||||
|
@ -5,37 +5,6 @@
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
static void
|
||||
mt7921_write_hw_txp(struct mt7921_dev *dev, struct mt76_tx_info *tx_info,
|
||||
void *txp_ptr, u32 id)
|
||||
{
|
||||
struct mt7921_hw_txp *txp = txp_ptr;
|
||||
struct mt7921_txp_ptr *ptr = &txp->ptr[0];
|
||||
int i, nbuf = tx_info->nbuf - 1;
|
||||
|
||||
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
|
||||
tx_info->nbuf = 1;
|
||||
|
||||
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
|
||||
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK;
|
||||
u32 addr = tx_info->buf[i + 1].addr;
|
||||
|
||||
if (i == nbuf - 1)
|
||||
len |= MT_TXD_LEN_LAST;
|
||||
|
||||
if (i & 1) {
|
||||
ptr->buf1 = cpu_to_le32(addr);
|
||||
ptr->len1 = cpu_to_le16(len);
|
||||
ptr++;
|
||||
} else {
|
||||
ptr->buf0 = cpu_to_le32(addr);
|
||||
ptr->len0 = cpu_to_le16(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
@ -44,8 +13,8 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
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 mt76_connac_hw_txp *txp;
|
||||
struct mt76_txwi_cache *t;
|
||||
struct mt7921_txp_common *txp;
|
||||
int id, pid;
|
||||
u8 *txwi = (u8 *)txwi_ptr;
|
||||
|
||||
@ -72,49 +41,18 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
}
|
||||
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
||||
mt7921_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, false);
|
||||
mt76_connac2_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, qid, 0);
|
||||
|
||||
txp = (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE);
|
||||
memset(txp, 0, sizeof(struct mt7921_txp_common));
|
||||
mt7921_write_hw_txp(dev, tx_info, txp, id);
|
||||
txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE);
|
||||
memset(txp, 0, sizeof(struct mt76_connac_hw_txp));
|
||||
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
|
||||
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
struct mt7921_txp_common *txp;
|
||||
int i;
|
||||
|
||||
txp = mt7921_txwi_to_txp(dev, t);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(txp->hw.ptr); i++) {
|
||||
struct mt7921_txp_ptr *ptr = &txp->hw.ptr[i];
|
||||
bool last;
|
||||
u16 len;
|
||||
|
||||
len = le16_to_cpu(ptr->len0);
|
||||
last = len & MT_TXD_LEN_LAST;
|
||||
len &= MT_TXD_LEN_MASK;
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len,
|
||||
DMA_TO_DEVICE);
|
||||
if (last)
|
||||
break;
|
||||
|
||||
len = le16_to_cpu(ptr->len1);
|
||||
last = len & MT_TXD_LEN_LAST;
|
||||
len &= MT_TXD_LEN_MASK;
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len,
|
||||
DMA_TO_DEVICE);
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
|
||||
struct ieee80211_sta *sta, bool clear_status,
|
||||
@ -124,7 +62,7 @@ mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
|
||||
__le32 *txwi;
|
||||
u16 wcid_idx;
|
||||
|
||||
mt7921_txp_skb_unmap(mdev, t);
|
||||
mt76_connac_txp_skb_unmap(mdev, t);
|
||||
if (!t->skb)
|
||||
goto out;
|
||||
|
||||
@ -150,7 +88,8 @@ out:
|
||||
static void
|
||||
mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
|
||||
{
|
||||
struct mt7921_tx_free *free = (struct mt7921_tx_free *)data;
|
||||
struct mt76_connac_tx_free *free = data;
|
||||
__le32 *tx_info = (__le32 *)(data + sizeof(*free));
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_txwi_cache *txwi;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
@ -165,11 +104,11 @@ mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
|
||||
|
||||
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
|
||||
if (WARN_ON_ONCE((void *)&free->info[count] > end))
|
||||
if (WARN_ON_ONCE((void *)&tx_info[count] > end))
|
||||
return;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
u32 msdu, info = le32_to_cpu(free->info[i]);
|
||||
u32 msdu, info = le32_to_cpu(tx_info[i]);
|
||||
u8 stat;
|
||||
|
||||
/* 1'b1: new wcid pair.
|
||||
@ -262,29 +201,6 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
}
|
||||
}
|
||||
|
||||
void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
|
||||
{
|
||||
if (!e->txwi) {
|
||||
dev_kfree_skb_any(e->skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* error path */
|
||||
if (e->skb == DMA_DUMMY_DATA) {
|
||||
struct mt76_txwi_cache *t;
|
||||
struct mt7921_txp_common *txp;
|
||||
u16 token;
|
||||
|
||||
txp = mt7921_txwi_to_txp(mdev, e->txwi);
|
||||
token = le16_to_cpu(txp->hw.msdu_id[0]) & ~MT_MSDU_ID_VALID;
|
||||
t = mt76_token_put(mdev, token);
|
||||
e->skb = t ? t->skb : NULL;
|
||||
}
|
||||
|
||||
if (e->skb)
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
|
||||
void mt7921_tx_token_put(struct mt7921_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *txwi;
|
||||
|
@ -26,10 +26,17 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
enum mt76_mcuq_id txq = MT_MCUQ_WM;
|
||||
int ret;
|
||||
|
||||
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(SUSPEND) ||
|
||||
cmd == MCU_UNI_CMD(OFFLOAD))
|
||||
mdev->mcu.timeout = HZ;
|
||||
else
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
txq = MT_MCUQ_FWDL;
|
||||
|
||||
@ -39,7 +46,7 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int mt7921e_mcu_init(struct mt7921_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7921_mcu_ops = {
|
||||
.headroom = sizeof(struct mt7921_mcu_txd),
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7921_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
@ -102,7 +109,7 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
{
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int i, err = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
|
||||
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);
|
||||
@ -114,12 +121,12 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
|
||||
dev_err(dev->mt76.dev, "firmware own failed\n");
|
||||
clear_bit(MT76_STATE_PM, &mphy->state);
|
||||
err = -EIO;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
pm->stats.last_doze_event = jiffies;
|
||||
pm->stats.awake_time += pm->stats.last_doze_event -
|
||||
pm->stats.last_wake_event;
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ static void mt7921s_unregister_device(struct mt7921_dev *dev)
|
||||
|
||||
mt76s_deinit(&dev->mt76);
|
||||
mt7921s_wfsys_reset(dev);
|
||||
mt7921_mcu_exit(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
@ -29,10 +29,17 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
if (dev->fw_assert)
|
||||
return -EBUSY;
|
||||
|
||||
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(SUSPEND) ||
|
||||
cmd == MCU_UNI_CMD(OFFLOAD))
|
||||
mdev->mcu.timeout = HZ;
|
||||
else
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
type = MT7921_SDIO_FWDL;
|
||||
|
||||
@ -72,7 +79,8 @@ static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev)
|
||||
int mt7921s_mcu_init(struct mt7921_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7921s_mcu_ops = {
|
||||
.headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd),
|
||||
.headroom = MT_SDIO_HDR_SIZE +
|
||||
sizeof(struct mt76_connac2_mcu_txd),
|
||||
.tailroom = MT_SDIO_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7921s_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
@ -99,8 +107,8 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
|
||||
struct sdio_func *func = dev->mt76.sdio.func;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int err = 0;
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
@ -118,8 +126,7 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
|
||||
|
||||
if (err < 0) {
|
||||
dev_err(dev->mt76.dev, "driver own failed\n");
|
||||
err = -EIO;
|
||||
goto out;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
clear_bit(MT76_STATE_PM, &mphy->state);
|
||||
@ -127,8 +134,8 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
|
||||
pm->stats.last_wake_event = jiffies;
|
||||
pm->stats.doze_time += pm->stats.last_wake_event -
|
||||
pm->stats.last_doze_event;
|
||||
out:
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
@ -136,8 +143,8 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
struct sdio_func *func = dev->mt76.sdio.func;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int err = 0;
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
@ -148,7 +155,7 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
2000, 1000000);
|
||||
if (err < 0) {
|
||||
dev_err(dev->mt76.dev, "mailbox ACK not cleared\n");
|
||||
goto err;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,18 +163,18 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
|
||||
err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
|
||||
!(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
|
||||
out:
|
||||
sdio_release_host(func);
|
||||
|
||||
err:
|
||||
if (err < 0) {
|
||||
dev_err(dev->mt76.dev, "firmware own failed\n");
|
||||
clear_bit(MT76_STATE_PM, &mphy->state);
|
||||
err = -EIO;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
pm->stats.last_doze_event = jiffies;
|
||||
pm->stats.awake_time += pm->stats.last_doze_event -
|
||||
pm->stats.last_wake_event;
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
@ -102,10 +102,17 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
u32 pad, ep;
|
||||
int ret;
|
||||
|
||||
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(SUSPEND) ||
|
||||
cmd == MCU_UNI_CMD(OFFLOAD))
|
||||
mdev->mcu.timeout = HZ;
|
||||
else
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
|
||||
if (cmd != MCU_CMD(FW_SCATTER))
|
||||
ep = MT_EP_OUT_INBAND_CMD;
|
||||
else
|
||||
@ -125,7 +132,8 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
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),
|
||||
.headroom = MT_SDIO_HDR_SIZE +
|
||||
sizeof(struct mt76_connac2_mcu_txd),
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7921u_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
@ -158,7 +166,7 @@ static void mt7921u_cleanup(struct mt7921_dev *dev)
|
||||
{
|
||||
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
mt7921u_wfsys_reset(dev);
|
||||
mt7921_mcu_exit(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ 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);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
@ -208,7 +208,7 @@ int mt7921u_mac_reset(struct mt7921_dev *dev)
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
mt7921_mcu_exit(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
@ -350,7 +350,6 @@ int mt76s_alloc_tx(struct mt76_dev *dev)
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
|
||||
q->qid = i;
|
||||
dev->phy.q_tx[i] = q;
|
||||
}
|
||||
|
||||
@ -358,7 +357,6 @@ int mt76s_alloc_tx(struct mt76_dev *dev)
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
|
||||
q->qid = MT_MCUQ_WM;
|
||||
dev->q_mcu[MT_MCUQ_WM] = q;
|
||||
|
||||
return 0;
|
||||
@ -517,8 +515,8 @@ static void mt76s_tx_status_data(struct work_struct *work)
|
||||
|
||||
static int
|
||||
mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
enum mt76_txq_id qid, struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt76_tx_info tx_info = {
|
||||
.skb = skb,
|
||||
@ -530,7 +528,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
return -ENOSPC;
|
||||
|
||||
skb->prev = skb->next = NULL;
|
||||
err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);
|
||||
err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -50,8 +50,8 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
|
||||
q->queued < q->ndesc / 2) {
|
||||
int ret;
|
||||
|
||||
ret = dev->queue_ops->tx_queue_skb(dev, q, skb_get(skb), wcid,
|
||||
NULL);
|
||||
ret = dev->queue_ops->tx_queue_skb(dev, q, qid, skb_get(skb),
|
||||
wcid, NULL);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
@ -101,7 +101,6 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
|
||||
u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
|
||||
IEEE80211_FCTL_FROMDS;
|
||||
struct mt76_testmode_data *td = &phy->test;
|
||||
bool ext_phy = phy != &phy->dev->phy;
|
||||
struct sk_buff **frag_tail, *head;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_hdr *hdr;
|
||||
@ -136,9 +135,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
|
||||
IEEE80211_TX_CTL_NO_ACK |
|
||||
IEEE80211_TX_CTL_NO_PS_BUFFER;
|
||||
|
||||
if (ext_phy)
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
frag_tail = &skb_shinfo(head)->frag_list;
|
||||
|
||||
for (i = 0; i < nfrags; i++) {
|
||||
|
@ -284,7 +284,7 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
|
||||
int idx;
|
||||
|
||||
non_aql = !info->tx_time_est;
|
||||
idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
|
||||
idx = dev->queue_ops->tx_queue_skb(dev, q, qid, skb, wcid, sta);
|
||||
if (idx < 0 || !sta)
|
||||
return idx;
|
||||
|
||||
@ -310,7 +310,6 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct mt76_queue *q;
|
||||
int qid = skb_get_queue_mapping(skb);
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
|
||||
if (mt76_testmode_enabled(phy)) {
|
||||
ieee80211_free_txskb(phy->hw, skb);
|
||||
@ -327,16 +326,13 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
||||
!ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
|
||||
qid = MT_TXQ_PSD;
|
||||
skb_set_queue_mapping(skb, qid);
|
||||
}
|
||||
|
||||
if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
|
||||
ieee80211_get_tx_rates(info->control.vif, sta, skb,
|
||||
info->control.rates, 1);
|
||||
|
||||
if (ext_phy)
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
q = phy->q_tx[qid];
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
@ -351,7 +347,6 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)
|
||||
{
|
||||
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
|
||||
struct ieee80211_tx_info *info;
|
||||
bool ext_phy = phy != &phy->dev->phy;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ieee80211_tx_dequeue(phy->hw, txq);
|
||||
@ -359,8 +354,7 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)
|
||||
return NULL;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (ext_phy)
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
|
||||
return skb;
|
||||
}
|
||||
@ -586,15 +580,25 @@ EXPORT_SYMBOL_GPL(mt76_txq_schedule_all);
|
||||
|
||||
void mt76_tx_worker_run(struct mt76_dev *dev)
|
||||
{
|
||||
mt76_txq_schedule_all(&dev->phy);
|
||||
if (dev->phy2)
|
||||
mt76_txq_schedule_all(dev->phy2);
|
||||
struct mt76_phy *phy;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
|
||||
phy = dev->phys[i];
|
||||
if (!phy)
|
||||
continue;
|
||||
|
||||
mt76_txq_schedule_all(phy);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
if (dev->phy.test.tx_pending)
|
||||
mt76_testmode_tx_pending(&dev->phy);
|
||||
if (dev->phy2 && dev->phy2->test.tx_pending)
|
||||
mt76_testmode_tx_pending(dev->phy2);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
|
||||
phy = dev->phys[i];
|
||||
if (!phy || !phy->test.tx_pending)
|
||||
continue;
|
||||
|
||||
mt76_testmode_tx_pending(phy);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_tx_worker_run);
|
||||
@ -697,17 +701,23 @@ EXPORT_SYMBOL_GPL(mt76_queue_tx_complete);
|
||||
|
||||
void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
|
||||
{
|
||||
struct mt76_phy *phy = &dev->phy, *phy2 = dev->phy2;
|
||||
struct mt76_queue *q, *q2 = NULL;
|
||||
struct mt76_phy *phy = &dev->phy;
|
||||
struct mt76_queue *q = phy->q_tx[0];
|
||||
|
||||
q = phy->q_tx[0];
|
||||
if (blocked == q->blocked)
|
||||
return;
|
||||
|
||||
q->blocked = blocked;
|
||||
if (phy2) {
|
||||
q2 = phy2->q_tx[0];
|
||||
q2->blocked = blocked;
|
||||
|
||||
phy = dev->phys[MT_BAND1];
|
||||
if (phy) {
|
||||
q = phy->q_tx[0];
|
||||
q->blocked = blocked;
|
||||
}
|
||||
phy = dev->phys[MT_BAND2];
|
||||
if (phy) {
|
||||
q = phy->q_tx[0];
|
||||
q->blocked = blocked;
|
||||
}
|
||||
|
||||
if (!blocked)
|
||||
|
@ -845,8 +845,8 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
|
||||
static int
|
||||
mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
enum mt76_txq_id qid, struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt76_tx_info tx_info = {
|
||||
.skb = skb,
|
||||
@ -858,7 +858,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
return -ENOSPC;
|
||||
|
||||
skb->prev = skb->next = NULL;
|
||||
err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);
|
||||
err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -937,7 +937,6 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
q->hw_idx = mt76u_ac_to_hwq(dev, i);
|
||||
q->qid = i;
|
||||
|
||||
dev->phy.q_tx[i] = q;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user