From e195dad1411594809cb955c96a7a514bcc4ad638 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Dec 2020 16:05:51 +0100 Subject: [PATCH 001/188] mt76: add support for 802.3 rx frames Do not try to access the header when receiving them Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/agg-rx.c | 13 ++++++----- drivers/net/wireless/mediatek/mt76/mac80211.c | 23 ++++++++++++++----- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 4 +++- .../net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- 8 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index df25c00d9e06..144e8a8910ba 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -122,6 +122,7 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames) struct ieee80211_bar *bar = mt76_skb_get_hdr(skb); struct mt76_wcid *wcid = status->wcid; struct mt76_rx_tid *tid; + u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; u16 seqno; if (!ieee80211_is_ctl(bar->frame_control)) @@ -130,9 +131,9 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames) if (!ieee80211_is_back_req(bar->frame_control)) return; - status->tid = le16_to_cpu(bar->control) >> 12; + status->qos_ctl = tidno = le16_to_cpu(bar->control) >> 12; seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num)); - tid = rcu_dereference(wcid->aggr[status->tid]); + tid = rcu_dereference(wcid->aggr[tidno]); if (!tid) return; @@ -147,12 +148,12 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames) void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); struct mt76_wcid *wcid = status->wcid; struct ieee80211_sta *sta; struct mt76_rx_tid *tid; bool sn_less; u16 seqno, head, size, idx; + u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; u8 ackp; __skb_queue_tail(frames, skb); @@ -161,18 +162,18 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) if (!sta) return; - if (!status->aggr) { + if (!status->aggr && !(status->flag & RX_FLAG_8023)) { mt76_rx_aggr_check_ctl(skb, frames); return; } /* not part of a BA session */ - ackp = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_ACK_POLICY_MASK; + ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK; if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) return; - tid = rcu_dereference(wcid->aggr[status->tid]); + tid = rcu_dereference(wcid->aggr[tidno]); if (!tid) return; diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 696d00d1976c..f9381bd96244 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -737,6 +737,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb) struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_wcid *wcid = status->wcid; struct ieee80211_hdr *hdr; + u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; int ret; if (!(status->flag & RX_FLAG_DECRYPTED)) @@ -757,12 +758,12 @@ mt76_check_ccmp_pn(struct sk_buff *skb) } BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0])); - ret = memcmp(status->iv, wcid->rx_key_pn[status->tid], + ret = memcmp(status->iv, wcid->rx_key_pn[tidno], sizeof(status->iv)); if (ret <= 0) return -EINVAL; /* replay */ - memcpy(wcid->rx_key_pn[status->tid], status->iv, sizeof(status->iv)); + memcpy(wcid->rx_key_pn[tidno], status->iv, sizeof(status->iv)); if (status->flag & RX_FLAG_IV_STRIPPED) status->flag |= RX_FLAG_PN_VALIDATED; @@ -785,6 +786,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, }; struct ieee80211_sta *sta; u32 airtime; + u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len); spin_lock(&dev->cc_lock); @@ -795,7 +797,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, return; sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); - ieee80211_sta_register_airtime(sta, status->tid, 0, airtime); + ieee80211_sta_register_airtime(sta, tidno, 0, airtime); } static void @@ -823,7 +825,6 @@ mt76_airtime_flush_ampdu(struct mt76_dev *dev) static void mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_wcid *wcid = status->wcid; @@ -831,6 +832,11 @@ mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb) return; if (!wcid || !wcid->sta) { + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (status->flag & RX_FLAG_8023) + return; + if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr)) return; @@ -864,10 +870,12 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) struct ieee80211_sta *sta; struct ieee80211_hw *hw; struct mt76_wcid *wcid = status->wcid; + u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; bool ps; hw = mt76_phy_hw(dev, status->ext_phy); - if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { + if (ieee80211_is_pspoll(hdr->frame_control) && !wcid && + !(status->flag & RX_FLAG_8023)) { sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); if (sta) wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv; @@ -885,6 +893,9 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) wcid->inactive_count = 0; + if (status->flag & RX_FLAG_8023) + return; + if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags)) return; @@ -902,7 +913,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) if (ps && (ieee80211_is_data_qos(hdr->frame_control) || ieee80211_is_qos_nullfunc(hdr->frame_control))) - ieee80211_sta_uapsd_trigger(sta, status->tid); + ieee80211_sta_uapsd_trigger(sta, tidno); if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps) return; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8bf45497cfca..a3455e2e1545 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -499,7 +499,7 @@ struct mt76_rx_status { u8 ext_phy:1; u8 aggr:1; - u8 tid; + u8 qos_ctl; u16 seqno; u16 freq; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index cc4e7bc48294..c29b60a87819 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -651,7 +651,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) status->aggr = unicast && !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->qos_ctl = *ieee80211_get_qos_ctl(hdr); status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 59fdd0fc2ad4..6a835568f4a3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -458,7 +458,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->aggr = unicast && !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->qos_ctl = *ieee80211_get_qos_ctl(hdr); status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 771bad60e1bc..0da37867cb64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -770,6 +770,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void *rxi) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ieee80211_hdr *hdr; struct mt76x02_rxwi *rxwi = rxi; struct mt76x02_sta *sta; u32 rxinfo = le32_to_cpu(rxwi->rxinfo); @@ -864,7 +865,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->freq = dev->mphy.chandef.chan->center_freq; status->band = dev->mphy.chandef.chan->band; - status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); + hdr = (struct ieee80211_hdr *)skb->data; + status->qos_ctl = *ieee80211_get_qos_ctl(hdr); status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); return mt76x02_mac_process_rate(dev, status, rate); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index e5a258958ac9..63524b48e291 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -556,7 +556,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->aggr = unicast && !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->qos_ctl = *ieee80211_get_qos_ctl(hdr); status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 3f9097481a5e..9468c9c3b9cf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -530,7 +530,7 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->aggr = unicast && !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->qos_ctl = *ieee80211_get_qos_ctl(hdr); status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); return 0; From cc4b3c139ad308fcd0086baa9dc13bf60e1b802f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 11 Oct 2020 23:37:12 +0200 Subject: [PATCH 002/188] mt76: mt7915: enable hw rx-amsdu de-aggregation Enable hw rx-amsdu de-aggregation support available in 7915 devices. This is a preliminary patch to enable rx checksum offload Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 49 ++++++++++++++++++- drivers/net/wireless/mediatek/mt76/mt76.h | 7 +++ .../net/wireless/mediatek/mt76/mt7915/init.c | 4 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 16 +++++- .../net/wireless/mediatek/mt76/mt7915/mac.h | 4 ++ 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index f9381bd96244..ef31026ac9d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -508,6 +508,39 @@ void mt76_free_device(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_free_device); +static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q) +{ + struct sk_buff *skb = phy->rx_amsdu[q].head; + struct mt76_dev *dev = phy->dev; + + phy->rx_amsdu[q].head = NULL; + phy->rx_amsdu[q].tail = NULL; + __skb_queue_tail(&dev->rx_skb[q], skb); +} + +static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q, + struct sk_buff *skb) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + + if (phy->rx_amsdu[q].head && + (!status->amsdu || status->first_amsdu || + status->seqno != phy->rx_amsdu[q].seqno)) + mt76_rx_release_amsdu(phy, q); + + if (!phy->rx_amsdu[q].head) { + phy->rx_amsdu[q].tail = &skb_shinfo(skb)->frag_list; + phy->rx_amsdu[q].seqno = status->seqno; + phy->rx_amsdu[q].head = skb; + } else { + *phy->rx_amsdu[q].tail = skb; + phy->rx_amsdu[q].tail = &skb->next; + } + + if (!status->amsdu || status->last_amsdu) + mt76_rx_release_amsdu(phy, 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; @@ -525,7 +558,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) phy->test.rx_stats.fcs_error[q]++; } #endif - __skb_queue_tail(&dev->rx_skb[q], skb); + + mt76_rx_release_burst(phy, q, skb); } EXPORT_SYMBOL_GPL(mt76_rx); @@ -937,13 +971,26 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, spin_lock(&dev->rx_lock); 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; } + skb_shinfo(skb)->frag_list = NULL; mt76_rx_convert(dev, skb, &hw, &sta); ieee80211_rx_list(hw, sta, skb, &list); + + /* subsequent amsdu frames */ + while (nskb) { + skb = nskb; + nskb = nskb->next; + skb->next = NULL; + + mt76_rx_convert(dev, skb, &hw, &sta); + ieee80211_rx_list(hw, sta, skb, &list); + } } spin_unlock(&dev->rx_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index a3455e2e1545..b301e5de30cc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -507,6 +507,7 @@ struct mt76_rx_status { u8 enc_flags; u8 encoding:2, bw:3, he_ru:3; u8 he_gi:2, he_dcm:1; + u8 amsdu:1, first_amsdu:1, last_amsdu:1; u8 rate_idx; u8 nss; u8 band; @@ -600,6 +601,12 @@ struct mt76_phy { struct delayed_work mac_work; u8 mac_work_count; + + struct { + struct sk_buff *head; + struct sk_buff **tail; + u16 seqno; + } rx_amsdu[__MT_RXQ_MAX]; }; struct mt76_dev { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index ad4e5b95158b..76dfcb76fb03 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -153,8 +153,8 @@ static void mt7915_mac_init(struct mt7915_dev *dev) int i; mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); - /* disable hardware de-agg */ - mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); + /* enable hardware de-agg */ + mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); for (i = 0; i < MT7915_WTBL_SIZE; i++) mt7915_mac_wtbl_update(dev, i, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 63524b48e291..48408ec4ad3c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -320,8 +320,9 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); + u32 rxd4 = le32_to_cpu(rxd[4]); bool unicast, insert_ccmp_hdr = false; - u8 remove_pad; + u8 remove_pad, amsdu_info; int i, idx; memset(status, 0, sizeof(*status)); @@ -338,6 +339,9 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) return -EINVAL; + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); @@ -541,6 +545,16 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); + amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); + status->amsdu = !!amsdu_info; + if (status->amsdu) { + status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; + status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; + memmove(skb->data + 2, skb->data, + ieee80211_get_hdrlen_from_skb(skb)); + skb_pull(skb, 2); + } + if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index 96ff3fb0d1f3..6ad8af835fd4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -86,6 +86,10 @@ enum rx_pkt_type { /* 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) From 94244d2ea503455cddec5a4de28d59c74e1aaf47 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Dec 2020 19:04:24 +0100 Subject: [PATCH 003/188] mt76: mt7915: add rx checksum offload support Set skb->ip_summed to CHECKSUM_UNNECESSARY if the hardware has validated the IP and TCP/UDP checksum Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 76dfcb76fb03..34a4fee24c48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -93,6 +93,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) hw->queues = 4; hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + hw->netdev_features = NETIF_F_RXCSUM; phy->slottime = 9; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 48408ec4ad3c..83dd504e7bf1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -317,10 +317,12 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) __le32 *rxd = (__le32 *)skb->data; __le32 *rxv = NULL; u32 mode = 0; + u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); + u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; bool unicast, insert_ccmp_hdr = false; u8 remove_pad, amsdu_info; int i, idx; @@ -366,6 +368,9 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (!sband->channels) return -EINVAL; + if ((rxd0 & csum_mask) == csum_mask) + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (rxd1 & MT_RXD1_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; From 90e3abf07c80a70f31227eea861f306312d5dbea Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Dec 2020 21:13:13 +0100 Subject: [PATCH 004/188] mt76: mt7915: add support for rx decapsulation offload For AP and Client mode, the hardware can pass received packets as 802.3 frames that can be passed to the network stack as-is. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7915/init.c | 1 + .../net/wireless/mediatek/mt76/mt7915/mac.c | 44 +++++++++++++++---- .../net/wireless/mediatek/mt76/mt7915/mac.h | 11 +++++ .../net/wireless/mediatek/mt76/mt7915/main.c | 21 ++++++++- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 25 +++++++++++ 6 files changed, 92 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index b301e5de30cc..695b58d7eadc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -197,6 +197,7 @@ enum mt76_wcid_flags { MT_WCID_FLAG_CHECK_PS, MT_WCID_FLAG_PS, MT_WCID_FLAG_4ADDR, + MT_WCID_FLAG_HDR_TRANS, }; #define MT76_N_WCIDS 288 diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 34a4fee24c48..c599b44a728c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -109,6 +109,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); ieee80211_hw_set(hw, WANT_MONITOR_VIF); hw->max_tx_fragments = 4; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 83dd504e7bf1..1a7291caf099 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -325,6 +325,10 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; bool unicast, insert_ccmp_hdr = false; u8 remove_pad, amsdu_info; + bool hdr_trans; + u16 seq_ctrl = 0; + u8 qos_ctl = 0; + __le16 fc = 0; int i, idx; memset(status, 0, sizeof(*status)); @@ -346,6 +350,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); + hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); if (status->wcid) { @@ -404,6 +409,13 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) rxd += 6; if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { + u32 v0 = le32_to_cpu(rxd[0]); + u32 v2 = le32_to_cpu(rxd[2]); + + fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0)); + qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2); + seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2); + rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -555,28 +567,42 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (status->amsdu) { status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; - memmove(skb->data + 2, skb->data, - ieee80211_get_hdrlen_from_skb(skb)); - skb_pull(skb, 2); + if (!hdr_trans) { + memmove(skb->data + 2, skb->data, + ieee80211_get_hdrlen_from_skb(skb)); + skb_pull(skb, 2); + } } - if (insert_ccmp_hdr) { + if (insert_ccmp_hdr && !hdr_trans) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); mt76_insert_ccmp_hdr(skb, key_id); } + if (!hdr_trans) { + hdr = mt76_skb_get_hdr(skb); + fc = hdr->frame_control; + if (ieee80211_is_data_qos(fc)) { + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); + qos_ctl = *ieee80211_get_qos_ctl(hdr); + } + } else { + status->flag &= ~(RX_FLAG_RADIOTAP_HE | + RX_FLAG_RADIOTAP_HE_MU); + status->flag |= RX_FLAG_8023; + } + if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) mt7915_mac_decode_he_radiotap(skb, status, rxv, mode); - hdr = mt76_skb_get_hdr(skb); - if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; status->aggr = unicast && - !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->qos_ctl = *ieee80211_get_qos_ctl(hdr); - status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + !ieee80211_is_qos_nullfunc(fc); + status->qos_ctl = qos_ctl; + status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index 6ad8af835fd4..0f929fb53027 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -101,6 +101,17 @@ enum rx_pkt_type { #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) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index d4969b2e1ffb..2406733f542d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -34,14 +34,14 @@ static int mt7915_start(struct ieee80211_hw *hw) if (!running) { mt7915_mcu_set_pm(dev, 0, 0); - mt7915_mcu_set_mac(dev, 0, true, false); + mt7915_mcu_set_mac(dev, 0, true, true); mt7915_mcu_set_scs(dev, 0, true); mt7915_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { mt7915_mcu_set_pm(dev, 1, 0); - mt7915_mcu_set_mac(dev, 1, true, false); + mt7915_mcu_set_mac(dev, 1, true, true); mt7915_mcu_set_scs(dev, 1, true); mt7915_mac_enable_nf(dev, 1); } @@ -888,6 +888,22 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, mt7915_mcu_sta_update_hdr_trans(dev, vif, sta); } +static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool enabled) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + + mt7915_mcu_sta_update_hdr_trans(dev, vif, sta); +} + const struct ieee80211_ops mt7915_ops = { .tx = mt7915_tx, .start = mt7915_start, @@ -920,6 +936,7 @@ const struct ieee80211_ops mt7915_ops = { .set_coverage_class = mt7915_set_coverage_class, .sta_statistics = mt7915_sta_statistics, .sta_set_4addr = mt7915_sta_set_4addr, + .sta_set_decap_offload = mt7915_sta_set_decap_offload, CFG80211_TESTMODE_CMD(mt76_testmode_cmd) CFG80211_TESTMODE_DUMP(mt76_testmode_dump) #ifdef CONFIG_MAC80211_DEBUGFS diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 195929242b72..6a8a1aa50756 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1685,6 +1685,7 @@ mt7915_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, return; msta = (struct mt7915_sta *)sta->drv_priv; + htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) { htr->to_ds = true; htr->from_ds = true; @@ -2869,6 +2870,27 @@ void mt7915_mcu_exit(struct mt7915_dev *dev) skb_queue_purge(&dev->mt76.mcu.res_q); } +static int +mt7915_mcu_set_rx_hdr_trans_blacklist(struct mt7915_dev *dev, int band) +{ + struct { + u8 operation; + u8 count; + u8 _rsv[2]; + u8 index; + u8 enable; + __le16 etype; + } req = { + .operation = 1, + .count = 1, + .enable = 1, + .etype = cpu_to_le16(ETH_P_PAE), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS), + &req, sizeof(req), false); +} + int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, bool hdr_trans) { @@ -2899,6 +2921,9 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, if (ret) return ret; + if (hdr_trans) + mt7915_mcu_set_rx_hdr_trans_blacklist(dev, band); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MAC_INIT_CTRL), &req_mac, sizeof(req_mac), true); } From 730d6d0da8d8f5905faafe645a5b3c08ac3f5a8f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 8 Feb 2021 17:07:27 +0100 Subject: [PATCH 005/188] mt76: mt7615: fix key set/delete issues There were multiple issues in the current key set/remove code: - deleting a key with the previous key index deletes the current key - BIP key would only be uploaded correctly initially and corrupted on rekey Rework the code to better keep track of multiple keys and check for the key index before deleting the current key Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 105 ++++++++++-------- .../net/wireless/mediatek/mt76/mt7615/main.c | 18 +-- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 695b58d7eadc..5561f81c64f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -223,6 +223,7 @@ struct mt76_wcid { u16 idx; u8 hw_key_idx; + u8 hw_key_idx2; u8 sta:1; u8 ext_phy:1; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 6a835568f4a3..c97ec70772f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1033,7 +1033,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; @@ -1050,22 +1050,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, memcpy(data + 16, key->key + 24, 8); memcpy(data + 24, key->key + 16, 8); } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) - memmove(data + 16, data, 16); - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) + if (cipher_mask == BIT(cipher)) memcpy(data, key->key, key->keylen); - else if (cipher == MT_CIPHER_BIP_CMAC_128) + else if (cipher != MT_CIPHER_BIP_CMAC_128) + memcpy(data, key->key, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memcpy(data + 16, key->key, 16); } } else { - if (wcid->cipher & ~BIT(cipher)) { - if (cipher != MT_CIPHER_BIP_CMAC_128) - memmove(data, data + 16, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memset(data + 16, 0, 16); - } else { + else if (cipher_mask) + memset(data, 0, 16); + if (!cipher_mask) memset(data, 0, sizeof(data)); - } } + mt76_wr_copy(dev, addr, data, sizeof(data)); return 0; @@ -1073,7 +1073,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, static int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, int keyidx, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1083,20 +1083,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, w0 = mt76_rr(dev, addr); w1 = mt76_rr(dev, addr + 4); - if (cmd == SET_KEY) { - w0 |= MT_WTBL_W0_RX_KEY_VALID | - FIELD_PREP(MT_WTBL_W0_RX_IK_VALID, - cipher == MT_CIPHER_BIP_CMAC_128); - if (cipher != MT_CIPHER_BIP_CMAC_128 || - !wcid->cipher) - w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); - } else { - if (!(wcid->cipher & ~BIT(cipher))) - w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | - MT_WTBL_W0_KEY_IDX); - if (cipher == MT_CIPHER_BIP_CMAC_128) - w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cipher_mask) + w0 |= MT_WTBL_W0_RX_KEY_VALID; + else + w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX); + if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128)) + w0 |= MT_WTBL_W0_RX_IK_VALID; + else + w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cmd == SET_KEY && + (cipher != MT_CIPHER_BIP_CMAC_128 || + cipher_mask == BIT(cipher))) { + w0 &= ~MT_WTBL_W0_KEY_IDX; + w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); } + mt76_wr(dev, MT_WTBL_RICR0, w0); mt76_wr(dev, MT_WTBL_RICR1, w1); @@ -1109,24 +1112,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, static void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); - if (cmd == SET_KEY) { - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); - } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && - wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128)) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, - MT_CIPHER_BIP_CMAC_128)); - else if (!(wcid->cipher & ~BIT(cipher))) - mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + if (!cipher_mask) { + mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + return; } + + if (cmd != SET_KEY) + return; + + if (cipher == MT_CIPHER_BIP_CMAC_128 && + cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128)) + return; + + mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, + FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); } int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, @@ -1135,25 +1139,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, enum set_key_cmd cmd) { enum mt7615_cipher_type cipher; + u16 cipher_mask = wcid->cipher; int err; cipher = mt7615_mac_get_cipher(key->cipher); if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP; - mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); - err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd); - if (err < 0) - return err; - - err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd); - if (err < 0) - return err; - if (cmd == SET_KEY) - wcid->cipher |= BIT(cipher); + cipher_mask |= BIT(cipher); else - wcid->cipher &= ~BIT(cipher); + cipher_mask &= ~BIT(cipher); + + mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd); + err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask, + cmd); + if (err < 0) + return err; + + err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask, + key->keyidx, cmd); + if (err < 0) + return err; + + wcid->cipher = cipher_mask; return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 25faf486d279..1aa6928f88fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -337,7 +337,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; - int idx = key->keyidx, err; + int idx = key->keyidx, err = 0; + u8 *wcid_keyidx = &wcid->hw_key_idx; /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -352,6 +353,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: + wcid_keyidx = &wcid->hw_key_idx2; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; case WLAN_CIPHER_SUITE_TKIP: @@ -369,12 +371,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt7615_mutex_acquire(dev); - if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); @@ -383,6 +386,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, else err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); +out: mt7615_mutex_release(dev); return err; From ebee7885bb12a8fe2c2f9bac87dbd87a05b645f9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Feb 2021 18:42:15 +0100 Subject: [PATCH 006/188] mt76: mt7615: fix tx skb dma unmap The first pointer in the txp needs to be unmapped as well, otherwise it will leak DMA mapping entries Fixes: 27d5c528a7ca ("mt76: fix double DMA unmap of the first buffer on 7615/7915") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index c97ec70772f3..9bae2f66e1ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -690,7 +690,7 @@ mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp) { int i; - for (i = 1; i < txp->nbuf; 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); } From 7dcf3c04f0aca746517a77433b33d40868ca4749 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Feb 2021 18:44:10 +0100 Subject: [PATCH 007/188] mt76: mt7915: fix tx skb dma unmap The first pointer in the txp needs to be unmapped as well, otherwise it will leak DMA mapping entries Reported-by: Ben Greear Fixes: 27d5c528a7ca ("mt76: fix double DMA unmap of the first buffer on 7615/7915") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 1a7291caf099..b5a41cb7fbda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1136,7 +1136,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev, int i; txp = mt7915_txwi_to_txp(dev, t); - for (i = 1; i < txp->nbuf; 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); } From 858ebf446bee7d5077bd99488aae617908c3f4fe Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Tue, 2 Feb 2021 09:59:53 +0100 Subject: [PATCH 008/188] mt76: mt7615: support loading EEPROM for MT7613BE EEPROM blobs for MT7613BE radios start with (little endian) 0x7663, which is also the PCI device ID for this device. The EEPROM is required for the radio to work at useful power levels, otherwise only the lowest power level is available. Suggested-by: Georgi Vlaev Tested-by: Stijn Segers Signed-off-by: Sander Vanheule Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 2eab23898c77..6dbaaf95ee38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7615: case 0x7622: + case 0x7663: return 0; default: return -EINVAL; From c1941b8902794c55328a220c5bf3654b1b54ba09 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 30 Jan 2021 13:28:36 +0100 Subject: [PATCH 009/188] mt76: mt7921: enable random mac addr during scanning Notify mac80211 mt7921 devices support random mac address during hw frequency scanning Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 89a13b4a74a4..4070f7156aa5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -95,6 +95,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->reg_notifier = mt7921_regd_notifier; + wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); From c2fa8edcca3b87c1d5cd6b9de00cb649abd636f5 Mon Sep 17 00:00:00 2001 From: Nigel Christian Date: Sat, 13 Feb 2021 22:02:37 -0500 Subject: [PATCH 010/188] mt76: mt7921: remove unnecessary variable In mt7921_pm_set() the variable "ret" is initialized to zero and then returned. Remove it and return zero. Signed-off-by: Nigel Christian Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 0dc8e25e18e4..4bc3dd99bd14 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -164,7 +164,6 @@ mt7921_pm_set(void *data, u64 val) { struct mt7921_dev *dev = data; struct mt76_phy *mphy = dev->phy.mt76; - int ret = 0; mt7921_mutex_acquire(dev); @@ -175,7 +174,7 @@ mt7921_pm_set(void *data, u64 val) mt7921_pm_interface_iter, mphy->priv); mt7921_mutex_release(dev); - return ret; + return 0; } static int From 00ac71ff8dc8b8b9ea07947164e8e5e06c520807 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 6 Feb 2021 11:35:41 +0100 Subject: [PATCH 011/188] mt76: mt7921: removed unused definitions in mcu.h Get rid of the following definitions in mt7921/mcu.h since they are not actually used: - MT7921_WTBL_UPDATE_MAX_SIZE - MT7921_STA_UPDATE_MAX_SIZE - MT7921_WTBL_UPDATE_BA_SIZE Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mcu.h | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index 2fdc62367b3f..fd67838cb565 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -251,29 +251,6 @@ enum { MT_IBF = BIT(1) /* implicit beamforming */ }; -#define MT7921_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_generic) + \ - sizeof(struct wtbl_rx) + \ - sizeof(struct wtbl_ht) + \ - sizeof(struct wtbl_vht) + \ - sizeof(struct wtbl_hdr_trans) +\ - sizeof(struct wtbl_ba) + \ - sizeof(struct wtbl_smps)) - -#define MT7921_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ - sizeof(struct sta_rec_basic) + \ - sizeof(struct sta_rec_ht) + \ - sizeof(struct sta_rec_he) + \ - sizeof(struct sta_rec_ba) + \ - sizeof(struct sta_rec_vht) + \ - sizeof(struct sta_rec_uapsd) + \ - sizeof(struct sta_rec_amsdu) + \ - sizeof(struct tlv) + \ - MT7921_WTBL_UPDATE_MAX_SIZE) - -#define MT7921_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_ba)) - #define STA_CAP_WMM BIT(0) #define STA_CAP_SGI_20 BIT(4) #define STA_CAP_SGI_40 BIT(5) From be2a2872d0b1db26222cfcd829f2d9e08f4c84c9 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 5 Feb 2021 13:13:01 +0800 Subject: [PATCH 012/188] mt76: always use WTBL_MAX_SIZE for tlv allocation Simplify WTBL defines. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.h | 24 ------------------- .../wireless/mediatek/mt76/mt76_connac_mcu.c | 2 +- .../wireless/mediatek/mt76/mt76_connac_mcu.h | 3 --- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/mcu.h | 3 --- 5 files changed, 2 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 3874f45da9eb..411ebb56baef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -362,30 +362,6 @@ enum { BSS_INFO_MAX_NUM }; -#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_generic) + \ - sizeof(struct wtbl_rx) + \ - sizeof(struct wtbl_ht) + \ - sizeof(struct wtbl_vht) + \ - sizeof(struct wtbl_tx_ps) + \ - sizeof(struct wtbl_hdr_trans) +\ - sizeof(struct wtbl_ba) + \ - sizeof(struct wtbl_bf) + \ - sizeof(struct wtbl_smps) + \ - sizeof(struct wtbl_pn) + \ - sizeof(struct wtbl_spe)) - -#define MT7615_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ - sizeof(struct sta_rec_basic) + \ - sizeof(struct sta_rec_ht) + \ - sizeof(struct sta_rec_vht) + \ - sizeof(struct sta_rec_uapsd) + \ - sizeof(struct tlv) + \ - MT7615_WTBL_UPDATE_MAX_SIZE) - -#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_ba)) - enum { CH_SWITCH_NORMAL = 0, CH_SWITCH_SCAN = 3, diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 6cbccfb05f8b..e6ad6cbeb803 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -287,7 +287,7 @@ mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid, &hdr.wlan_idx_hi); if (!nskb) { nskb = mt76_mcu_msg_alloc(dev, NULL, - MT76_CONNAC_WTBL_UPDATE_BA_SIZE); + MT76_CONNAC_WTBL_UPDATE_MAX_SIZE); if (!nskb) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index c1e1df5f7cd7..9c26b90655a7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -304,9 +304,6 @@ struct wtbl_raw { sizeof(struct tlv) + \ MT76_CONNAC_WTBL_UPDATE_MAX_SIZE) -#define MT76_CONNAC_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_ba)) - enum { STA_REC_BASIC, STA_REC_RA, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 6a8a1aa50756..a9c4a003560d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -592,7 +592,7 @@ mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta, if (!nskb) { nskb = mt76_mcu_msg_alloc(&dev->mt76, NULL, - MT7915_WTBL_UPDATE_BA_SIZE); + MT7915_WTBL_UPDATE_MAX_SIZE); if (!nskb) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 2d584142c27b..2a2f7bf2c94b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -1080,9 +1080,6 @@ enum { sizeof(struct tlv) + \ MT7915_WTBL_UPDATE_MAX_SIZE) -#define MT7915_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_ba)) - #define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct bss_info_omac) + \ sizeof(struct bss_info_basic) +\ From 4b36cc6b390f18dbc59a45fb4141f90d7dfe2b23 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sun, 7 Feb 2021 16:09:17 +0100 Subject: [PATCH 013/188] mt76: mt76x0: disable GTK offloading When operating two VAP on a MT7610 with encryption (PSK2, SAE, OWE), only the first one to be created will transmit properly encrypteded frames. All subsequently created VAPs will sent out frames with the payload left unencrypted, breaking multicast traffic (ICMP6 NDP) and potentially disclosing information to a third party. Disable GTK offloading and encrypt these frames in software to circumvent this issue. THis only seems to be necessary on MT7610 chips, as MT7612 is not affected from our testing. Signed-off-by: David Bauer Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index ab671e21f882..02db5d66735d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -447,6 +447,10 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) return -EOPNOTSUPP; + /* MT76x0 GTK offloading does not work with more than one VIF */ + if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL; wcid = msta ? &msta->wcid : &mvif->group_wcid; From baa3afb39e94965f4ca5b5d3d274379504b8fa24 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 12 Feb 2021 12:51:05 +0100 Subject: [PATCH 014/188] mt76: connac: always check return value from mt76_connac_mcu_alloc_wtbl_req Even if this is not a real bug since mt76_connac_mcu_alloc_wtbl_req routine can fails just if nskb is NULL , always check return value from mt76_connac_mcu_alloc_wtbl_req in order to avoid possible future mistake. Reported-by: Dan Carpenter Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 631596fc2f36..4ecbd5406e2a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1040,6 +1040,9 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev, wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx, sta_wtbl, wtbl_hdr); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index e6ad6cbeb803..ac8d6ad76054 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -833,6 +833,9 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy, wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_RESET_AND_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + if (enable) { mt76_connac_mcu_wtbl_generic_tlv(dev, skb, vif, sta, sta_wtbl, wtbl_hdr); From 45f93e368211fbbd247e1ece254ffb121e20fa10 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 12 Feb 2021 20:30:04 +0100 Subject: [PATCH 015/188] mt76: mt7915: always check return value from mt7915_mcu_alloc_wtbl_req As done for mt76_connac_mcu_alloc_wtbl_req, even if this is not a real bug since mt7915_mcu_alloc_wtbl_req routine can fails just if nskb is NULL, always check return value from mt7915_mcu_alloc_wtbl_req in order to avoid possible future mistake. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index a9c4a003560d..6c429a2b15c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1188,6 +1188,9 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev, wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, @@ -1705,6 +1708,9 @@ int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, return -ENOMEM; wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(WTBL_UPDATE), @@ -1729,6 +1735,9 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); return mt76_mcu_skb_send_msg(&dev->mt76, skb, @@ -2254,6 +2263,9 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + if (enable) { mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); From 7715a1d54bdf47f89194b0a088e07dcd76820f51 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 2 Feb 2021 21:57:59 +0800 Subject: [PATCH 016/188] mt76: use PCI_VENDOR_ID_MEDIATEK to avoid open coded Use PCI standard defines. Signed-off-by: Ryder Lee Acked-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/pci.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/pci.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c index 06fa28f645f2..aa6cb668b012 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c @@ -7,7 +7,7 @@ #include "mt7603.h" static const struct pci_device_id mt76pci_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7603) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7603) }, { }, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 71487f532f36..11f169cdd603 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -13,9 +13,9 @@ #include "mcu.h" static const struct pci_device_id mt7615_pci_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7615) }, - { PCI_DEVICE(0x14c3, 0x7663) }, - { PCI_DEVICE(0x14c3, 0x7611) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7615) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7663) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7611) }, { }, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 02d0aa0b815e..5847f943e8da 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -221,9 +221,9 @@ mt76x0e_remove(struct pci_dev *pdev) } static const struct pci_device_id mt76x0e_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7610) }, - { PCI_DEVICE(0x14c3, 0x7630) }, - { PCI_DEVICE(0x14c3, 0x7650) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7610) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7630) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7650) }, { }, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index ecaf85b483ac..adf288e50e21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -10,9 +10,9 @@ #include "mt76x2.h" static const struct pci_device_id mt76x2e_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7662) }, - { PCI_DEVICE(0x14c3, 0x7612) }, - { PCI_DEVICE(0x14c3, 0x7602) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7662) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7612) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7602) }, { }, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 5570b4a50531..33ed952d7f4c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -13,7 +13,7 @@ #include "../trace.h" static const struct pci_device_id mt7921_pci_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7961) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961) }, { }, }; From 5e30931494b4940ba74fa5796ca0b6d7e4c84e88 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:44 +0100 Subject: [PATCH 017/188] mt76: mt7921: fix suspend/resume sequence Any pcie access should happen in pci D0 state and we should give ownership back to the device at the end of the suspend procedure. Fixes: 1d8efc741df80 ("mt76: mt7921: introduce Runtime PM support") Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 33ed952d7f4c..7e040c38c3b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -209,12 +209,12 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) /* disable interrupt */ mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); - pci_save_state(pdev); - err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); + err = mt7921_mcu_fw_pmctrl(dev); if (err) goto restore; - err = mt7921_mcu_drv_pmctrl(dev); + pci_save_state(pdev); + err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); if (err) goto restore; @@ -237,16 +237,16 @@ static int mt7921_pci_resume(struct pci_dev *pdev) struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); int i, err; - err = mt7921_mcu_fw_pmctrl(dev); - if (err < 0) - return 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; + /* enable interrupt */ mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | From 782b3e86ea970e899f8e723db9f64708a15ca30e Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:45 +0100 Subject: [PATCH 018/188] mt76: mt7921: fix memory leak in mt7921_coredump_work Fix possible memory leak in mt7921_coredump_work. Fixes: 1c099ab44727c ("mt76: mt7921: add MCU support") Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 9468c9c3b9cf..8befa8167cde 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1503,8 +1503,10 @@ void mt7921_coredump_work(struct work_struct *work) break; skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); - if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) - break; + if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { + dev_kfree_skb(skb); + continue; + } memcpy(data, skb->data, skb->len); data += skb->len; From 159f6dd619d953e2a137bfb42cbce7cbed621c76 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:46 +0100 Subject: [PATCH 019/188] mt76: mt7921: switch to new api for hardware beacon filter Current firmware only supports new api for enabling hardware beacon filter. Fixes: 1d8efc741df80 ("mt76: mt7921: introduce Runtime PM support") Beacon filter cmd have to rely on the associatied access point's beacon interval and DTIM information. Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/main.c | 49 +++++++++++++------ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 8 ++- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 729f6c42cdde..11d85cf9cfb8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -295,15 +295,6 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, if (ret) goto out; - if (dev->pm.enable) { - ret = mt7921_mcu_set_bss_pm(dev, vif, true); - if (ret) - goto out; - - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; - mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); - } - dev->mt76.vif_mask |= BIT(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); @@ -349,13 +340,6 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, phy->monitor_vif = NULL; mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - - if (dev->pm.enable) { - mt7921_mcu_set_bss_pm(dev, vif, false); - mt76_clear(dev, MT_WF_RFCR(0), - MT_WF_RFCR_DROP_OTHER_BEACON); - } - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); @@ -561,6 +545,36 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, mt7921_mutex_release(dev); } +static int +mt7921_bss_bcnft_apply(struct mt7921_dev *dev, struct ieee80211_vif *vif, + bool assoc) +{ + int ret; + + if (!dev->pm.enable) + return 0; + + if (assoc) { + ret = mt7921_mcu_uni_bss_bcnft(dev, vif, true); + if (ret) + return ret; + + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); + + return 0; + } + + ret = mt7921_mcu_set_bss_pm(dev, vif, false); + if (ret) + return ret; + + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; + mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); + + return 0; +} + static void mt7921_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -587,6 +601,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_PS) mt7921_mcu_uni_bss_ps(dev, vif); + if (changed & BSS_CHANGED_ASSOC) + mt7921_bss_bcnft_apply(dev, vif, info->assoc); + mt7921_mutex_release(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index b5cc72e7e81c..b0f8c29f756b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1292,8 +1292,14 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt7921_phy *phy = priv; struct mt7921_dev *dev = phy->dev; + int ret; - if (mt7921_mcu_set_bss_pm(dev, vif, dev->pm.enable)) + if (dev->pm.enable) + ret = mt7921_mcu_uni_bss_bcnft(dev, vif, true); + else + ret = mt7921_mcu_set_bss_pm(dev, vif, false); + + if (ret) return; if (dev->pm.enable) { From a7e3033fcdb60ad51b03896ae99ad9447389bed0 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:47 +0100 Subject: [PATCH 020/188] mt76: connac: fix up the setting for ht40 mode in mt76_connac_mcu_uni_add_bss Use proper value for ht40 mode configuration in mt76_connac_mcu_uni_add_bss routine and not ht20 one Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") Co-developed-by: Soul Huang Signed-off-by: Soul Huang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index ac8d6ad76054..81515419b5b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1198,6 +1198,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, .center_chan = ieee80211_frequency_to_channel(freq1), .center_chan2 = ieee80211_frequency_to_channel(freq2), .tx_streams = hweight8(phy->antenna_mask), + .ht_op_info = 4, /* set HT 40M allowed */ .rx_streams = phy->chainmask, .short_st = true, }, @@ -1290,6 +1291,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, case NL80211_CHAN_WIDTH_20: default: rlm_req.rlm.bw = CMD_CBW_20MHZ; + rlm_req.rlm.ht_op_info = 0; break; } From 0940605a2a70803fc3362eeccba4c31adf4e70e7 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:48 +0100 Subject: [PATCH 021/188] mt76: mt7921: fixup rx bitrate statistics Since the related rx bitrate fields have been moved to group3 in Rxv, fix rx bitrate statistics in mt7921_mac_fill_rx routine. Fixes: 163f4d22c118d ("mt76: mt7921: add MAC support") Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mac.c | 159 +++++++++--------- .../net/wireless/mediatek/mt76/mt7921/mac.h | 10 +- 2 files changed, 88 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 8befa8167cde..76d5f194706f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -400,7 +400,9 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) /* RXD Group 3 - P-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { - u32 v0, v1, v2; + u8 stbc, gi; + u32 v0, v1; + bool cck; rxv = rxd; rxd += 2; @@ -409,7 +411,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) v0 = le32_to_cpu(rxv[0]); v1 = le32_to_cpu(rxv[1]); - v2 = le32_to_cpu(rxv[2]); if (v0 & MT_PRXV_HT_AD_CODE) status->enc_flags |= RX_ENC_FLAG_LDPC; @@ -429,87 +430,87 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->chain_signal[i]); } - /* RXD Group 5 - C-RXV */ - if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { - u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); - u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); - bool cck = false; + 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 > 9) + return -EINVAL; + break; + case MT_PHY_TYPE_HE_MU: + status->flag |= RX_FLAG_RADIOTAP_HE_MU; + fallthrough; + 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; + status->flag |= RX_FLAG_RADIOTAP_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; + + if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { rxd += 18; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; - - idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); - mode = FIELD_GET(MT_CRXV_TX_MODE, v2); - - 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 > 9) - return -EINVAL; - break; - case MT_PHY_TYPE_HE_MU: - status->flag |= RX_FLAG_RADIOTAP_HE_MU; - fallthrough; - 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; - status->flag |= RX_FLAG_RADIOTAP_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_CRXV_FRAME_MODE, v2)) { - 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; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h index a0c1fa0f20e4..109c8849d106 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h @@ -97,18 +97,24 @@ enum rx_pkt_type { #define MT_RXD3_NORMAL_PF_MODE BIT(29) #define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) -/* P-RXV */ +/* 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_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) -#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0) + +/* 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) From 9dfd2785ac730f617b06b572683d76bfc51b67c2 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:49 +0100 Subject: [PATCH 022/188] mt76: mt7921: add flush operation add flush operation to make sure cfg80211_mlme_deauth is able to flush the deauthtication frame into air immediately. Co-developed-by: YN Chen Signed-off-by: YN Chen Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 11d85cf9cfb8..f7552f5201b4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1137,6 +1137,15 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, } #endif /* CONFIG_PM */ +static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ + struct mt7921_dev *dev = mt7921_hw_dev(hw); + + wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy), + HZ / 2); +} + const struct ieee80211_ops mt7921_ops = { .tx = mt7921_tx, .start = mt7921_start, @@ -1175,4 +1184,5 @@ const struct ieee80211_ops mt7921_ops = { .set_wakeup = mt7921_set_wakeup, .set_rekey_data = mt7921_set_rekey_data, #endif /* CONFIG_PM */ + .flush = mt7921_flush, }; From 7139b5c0c98af1e2a04bd9ff09d2c01c40f1da41 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 19 Feb 2021 18:28:51 +0100 Subject: [PATCH 023/188] mt76: connac: update sched_scan cmd usage Update sched_scan command usage according to the current firmware submitted into linux-firmware.git. Fixes: 80fc1e37c0eb ("mt76: mt7921: rely on mt76_connac_mcu module for sched_scan and hw_scan") Co-developed-by: Soul Huang Signed-off-by: Soul Huang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 5 ----- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 5 +++++ .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 7 +++++-- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 14 +++++++++++--- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 491841bc6291..5ef19fbee6bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -408,11 +408,6 @@ static inline bool is_mt7615(struct mt76_dev *dev) return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611; } -static inline bool is_mt7663(struct mt76_dev *dev) -{ - return mt76_chip(dev) == 0x7663; -} - static inline bool is_mt7611(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7611; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 0d58606391b0..b811f3c410a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -73,6 +73,11 @@ static inline bool is_mt7921(struct mt76_dev *dev) return mt76_chip(dev) == 0x7961; } +static inline bool is_mt7663(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7663; +} + 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); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 81515419b5b6..125e02b34a5f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1438,10 +1438,13 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, req->version = 1; req->seq_num = mvif->scan_seq_num | ext_phy << 7; - if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { - get_random_mask_addr(req->random_mac, sreq->mac_addr, + if (is_mt7663(phy->dev) && + (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + get_random_mask_addr(req->mt7663.random_mac, sreq->mac_addr, sreq->mac_addr_mask); req->scan_func = 1; + } else if (is_mt7921(phy->dev)) { + req->mt7921.bss_idx = mvif->idx; } req->ssids_num = sreq->n_ssids; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 9c26b90655a7..8478f019f5d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -756,11 +756,19 @@ struct mt76_connac_sched_scan_req { u8 channel_type; u8 channels_num; u8 intervals_num; - u8 scan_func; /* BIT(0) eable random mac address */ + u8 scan_func; /* MT7663: BIT(0) eable random mac address */ struct mt76_connac_mcu_scan_channel channels[64]; __le16 intervals[MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL]; - u8 random_mac[ETH_ALEN]; /* valid when BIT(0) in scan_func is set */ - u8 pad2[58]; + union { + struct { + u8 random_mac[ETH_ALEN]; + u8 pad2[58]; + } mt7663; + struct { + u8 bss_idx; + u8 pad2[63]; + } mt7921; + }; } __packed; struct mt76_connac_sched_scan_done { From aa40528a5bca990ef8f6a82eb26d23c81b4b3cff Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 26 Jul 2020 13:09:51 +0200 Subject: [PATCH 024/188] mt76: use threaded NAPI With threaded NAPI, the rx handler function is no longer bound to the CPU that fired the interrupt, which significantly helps to spread the workload over multiple CPUs, especially when multiple devices are using threaded NAPI at the same time. Exclude the tx handler from threaded NAPI by using a separate dummy netdev. The work is small and short-lived enough that it makes more sense to run it in softirq instead of creating a dedicated thread Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 6 ++++-- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 2f27c43ad76d..6273b2cfce4f 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -602,7 +602,6 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) dev = container_of(napi->dev, struct mt76_dev, napi_dev); qid = napi - dev->napi; - local_bh_disable(); rcu_read_lock(); do { @@ -612,7 +611,6 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) } while (cur && done < budget); rcu_read_unlock(); - local_bh_enable(); if (done < budget && napi_complete(napi)) dev->drv->rx_poll_complete(dev, qid); @@ -626,6 +624,10 @@ mt76_dma_init(struct mt76_dev *dev) int i; init_dummy_netdev(&dev->napi_dev); + init_dummy_netdev(&dev->tx_napi_dev); + snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s", + wiphy_name(dev->hw->wiphy)); + dev->napi_dev.threaded = 1; mt76_for_each_q_rx(dev, i) { netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5561f81c64f7..4d71ca228de2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -637,6 +637,7 @@ struct mt76_dev { struct mt76_mcu mcu; struct net_device napi_dev; + struct net_device tx_napi_dev; spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; struct sk_buff_head rx_skb[__MT_RXQ_MAX]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 0086f18cb79a..2b6244116842 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -223,7 +223,7 @@ int mt7603_dma_init(struct mt7603_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7603_poll_tx, NAPI_POLL_WEIGHT); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 25e3069cf2b1..2e3120eb2da9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -245,7 +245,7 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7615_poll_tx, NAPI_POLL_WEIGHT); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index e7a46ac97f51..fc12824ab74e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -230,7 +230,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt76x02_poll_tx, NAPI_POLL_WEIGHT); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index bf51304a770b..3c961bf55e97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -325,7 +325,7 @@ int mt7915_dma_init(struct mt7915_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7915_poll_tx, NAPI_POLL_WEIGHT); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index cd9665610284..60de29a921a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -299,7 +299,7 @@ int mt7921_dma_init(struct mt7921_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7921_poll_tx, NAPI_POLL_WEIGHT); napi_enable(&dev->mt76.tx_napi); From e78d73e01db3309bbc099be87a5157d3c710fcc8 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 18 Feb 2021 09:34:38 +0800 Subject: [PATCH 025/188] mt76: mt7615: enable hw rx-amsdu de-aggregation Enable hw rx-amsdu de-aggregation support. This is a preliminary patch to enable rx checksum offload. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 15 ++++++++++++++- drivers/net/wireless/mediatek/mt76/mt7615/mac.h | 3 +++ drivers/net/wireless/mediatek/mt76/mt7615/regs.h | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 571390fa4de7..a97cc723094c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -116,10 +116,9 @@ mt7615_mac_init(struct mt7615_dev *dev) mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); - /* disable hdr translation and hw AMSDU */ mt76_wr(dev, MT_DMA_DCR0, FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) | - MT_DMA_DCR0_RX_VEC_DROP); + MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN); /* disable TDLS filtering */ mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN); mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 9bae2f66e1ce..928edd158f64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -238,7 +238,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) bool unicast, remove_pad, insert_ccmp_hdr = false; int phy_idx; int i, idx; - u8 chfreq; + u8 chfreq, amsdu_info; memset(status, 0, sizeof(*status)); @@ -254,6 +254,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) else phy_idx = -1; + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); @@ -446,6 +449,16 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); + amsdu_info = FIELD_GET(MT_RXD1_NORMAL_PAYLOAD_FORMAT, rxd1); + status->amsdu = !!amsdu_info; + if (status->amsdu) { + status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME; + status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME; + memmove(skb->data + 2, skb->data, + ieee80211_get_hdrlen_from_skb(skb)); + skb_pull(skb, 2); + } + if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 169f4e17b5b4..ed009d085a53 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -33,6 +33,9 @@ enum rx_pkt_type { #define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) #define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24) +#define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0) +#define MT_RXD1_MID_AMSDU_FRAME BIT(1) +#define MT_RXD1_LAST_AMSDU_FRAME BIT(0) #define MT_RXD1_NORMAL_HDR_TRANS BIT(23) #define MT_RXD1_NORMAL_HDR_OFFSET BIT(22) #define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 6e5db015b32c..4ebffe52cb8e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -368,6 +368,7 @@ enum mt7615_reg_base { #define MT_DMA_DCR0 MT_WF_DMA(0x000) #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) +#define MT_DMA_DCR0_DAMSDU_EN BIT(16) #define MT_DMA_DCR0_RX_VEC_DROP BIT(17) #define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40) From 2122dfbfd0bd951a6bded5fbd9a1e87b37c41caa Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 18 Feb 2021 09:34:39 +0800 Subject: [PATCH 026/188] mt76: mt7615: add rx checksum offload support Set skb->ip_summed to CHECKSUM_UNNECESSARY if the hardware has validated the IP and TCP/UDP checksum Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index a97cc723094c..fd38737a27bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -329,6 +329,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) hw->max_rates = 3; hw->max_report_rates = 7; hw->max_rate_tries = 11; + hw->netdev_features = NETIF_F_RXCSUM; phy->slottime = 9; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 928edd158f64..340beff0e121 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -234,6 +234,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); + u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; __le32 rxd12 = rxd[12]; bool unicast, remove_pad, insert_ccmp_hdr = false; int phy_idx; @@ -271,6 +272,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } + if ((rxd0 & csum_mask) == csum_mask) + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; From d4b98c63d7a772cfc2ed68c646915d5b3988e934 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 18 Feb 2021 09:34:40 +0800 Subject: [PATCH 027/188] mt76: mt7615: add support for rx decapsulation offload For AP and Client mode, the hardware can pass received packets as 802.3 frames that can be passed to the network stack as-is. Tested-by: Frank Wunderlich Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 5 ++- .../net/wireless/mediatek/mt76/mt7615/mac.c | 44 ++++++++++++++----- .../net/wireless/mediatek/mt76/mt7615/mac.h | 5 +++ .../net/wireless/mediatek/mt76/mt7615/main.c | 17 +++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 39 ++++++++++++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 4 ++ .../net/wireless/mediatek/mt76/mt7615/regs.h | 1 + .../wireless/mediatek/mt76/mt76_connac_mcu.c | 19 ++++++++ .../wireless/mediatek/mt76/mt76_connac_mcu.h | 6 ++- 9 files changed, 127 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index fd38737a27bd..88a2ee7e7143 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -118,7 +118,8 @@ mt7615_mac_init(struct mt7615_dev *dev) mt76_wr(dev, MT_DMA_DCR0, FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) | - MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN); + MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN | + MT_DMA_DCR0_RX_HDR_TRANS_EN); /* disable TDLS filtering */ mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN); mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN); @@ -128,6 +129,7 @@ mt7615_mac_init(struct mt7615_dev *dev) } else { mt7615_init_mac_chain(dev, 1); } + mt7615_mcu_set_rx_hdr_trans_blacklist(dev); } static void @@ -360,6 +362,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); if (is_mt7615(&phy->dev->mt76)) hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 340beff0e121..f2dd56674acb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -236,10 +236,12 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) u32 rxd2 = le32_to_cpu(rxd[2]); u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; __le32 rxd12 = rxd[12]; - bool unicast, remove_pad, insert_ccmp_hdr = false; + bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false; int phy_idx; int i, idx; - u8 chfreq, amsdu_info; + u8 chfreq, amsdu_info, qos_ctl = 0; + u16 seq_ctrl = 0; + __le16 fc = 0; memset(status, 0, sizeof(*status)); @@ -260,6 +262,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); + hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS; status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); if (status->wcid) { @@ -295,6 +298,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) rxd += 4; if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { + u32 v0 = le32_to_cpu(rxd[0]); + u32 v2 = le32_to_cpu(rxd[2]); + + fc = cpu_to_le16(FIELD_GET(MT_RXD4_FRAME_CONTROL, v0)); + qos_ctl = FIELD_GET(MT_RXD6_QOS_CTL, v2); + seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, v2); + rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -458,25 +468,37 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (status->amsdu) { status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME; status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME; - memmove(skb->data + 2, skb->data, - ieee80211_get_hdrlen_from_skb(skb)); - skb_pull(skb, 2); + if (!hdr_trans) { + memmove(skb->data + 2, skb->data, + ieee80211_get_hdrlen_from_skb(skb)); + skb_pull(skb, 2); + } } - if (insert_ccmp_hdr) { + if (insert_ccmp_hdr && !hdr_trans) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); mt76_insert_ccmp_hdr(skb, key_id); } - hdr = (struct ieee80211_hdr *)skb->data; - if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + if (!hdr_trans) { + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + if (ieee80211_is_data_qos(fc)) { + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); + qos_ctl = *ieee80211_get_qos_ctl(hdr); + } + } else { + status->flag |= RX_FLAG_8023; + } + + if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; status->aggr = unicast && - !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->qos_ctl = *ieee80211_get_qos_ctl(hdr); - status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + !ieee80211_is_qos_nullfunc(fc); + status->qos_ctl = qos_ctl; + status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index ed009d085a53..6bf9da040196 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -81,6 +81,11 @@ enum rx_pkt_type { #define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8) #define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) +#define MT_RXD4_FRAME_CONTROL GENMASK(15, 0) + +#define MT_RXD6_SEQ_CTRL GENMASK(15, 0) +#define MT_RXD6_QOS_CTL GENMASK(31, 16) + #define MT_RXV1_ACID_DET_H BIT(31) #define MT_RXV1_ACID_DET_L BIT(30) #define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 1aa6928f88fc..1cf40f85eb55 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -1087,6 +1087,22 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, return 0; } +static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool enabled) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + + mt7615_mcu_sta_update_hdr_trans(dev, vif, sta); +} + #ifdef CONFIG_PM static int mt7615_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) @@ -1187,6 +1203,7 @@ const struct ieee80211_ops mt7615_ops = { .sta_remove = mt7615_sta_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7615_set_key, + .sta_set_decap_offload = mt7615_sta_set_decap_offload, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, .wake_tx_queue = mt7615_wake_tx_queue, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 4ecbd5406e2a..393ce09d3956 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1097,6 +1097,25 @@ static const struct mt7615_mcu_ops sta_update_ops = { .set_fw_ctrl = mt7615_mcu_fw_pmctrl, }; +int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb = NULL; + + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, + true); +} + static int mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) { @@ -2500,6 +2519,26 @@ out: return ret; } +int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev) +{ + struct { + u8 operation; + u8 count; + u8 _rsv[2]; + u8 index; + u8 enable; + __le16 etype; + } req = { + .operation = 1, + .count = 1, + .enable = 1, + .etype = cpu_to_le16(ETH_P_PAE), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, + &req, sizeof(req), false); +} + int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 5ef19fbee6bd..aa6fe65f42a7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -519,6 +519,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, 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_sta_update_hdr_trans(struct mt7615_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +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, const struct mt7615_dfs_pulse *pulse); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 4ebffe52cb8e..1fd7f183629e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -370,6 +370,7 @@ enum mt7615_reg_base { #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) #define MT_DMA_DCR0_DAMSDU_EN BIT(16) #define MT_DMA_DCR0_RX_VEC_DROP BIT(17) +#define MT_DMA_DCR0_RX_HDR_TRANS_EN BIT(19) #define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40) #define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 125e02b34a5f..ab9e48c19508 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -392,6 +392,25 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif, uapsd->max_sp = sta->max_sp; } +void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) +{ + struct mt76_wcid *wcid; + struct wtbl_hdr_trans *htr; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS, + sizeof(*htr), + wtbl_tlv, sta_wtbl); + htr = (struct wtbl_hdr_trans *)tlv; + + wcid = (struct mt76_wcid *)sta->drv_priv; + htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv); + void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 8478f019f5d3..950e68e11ddd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -210,7 +210,7 @@ struct wtbl_hdr_trans { __le16 len; u8 to_ds; u8 from_ds; - u8 disable_rx_trans; + u8 no_rx_trans; u8 rsv; } __packed; @@ -922,6 +922,10 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta, void *sta_wtbl, void *wtbl_tlv); +void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv); void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif); From 49cc85059a2cb656f96ff3693f891e8fe8f669a9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 19 Feb 2021 18:22:11 +0100 Subject: [PATCH 028/188] mt76: mt7615: fix memory leak in mt7615_coredump_work Similar to the issue fixed in mt7921_coredump_work, fix a possible memory leak in mt7615_coredump_work routine. Fixes: d2bf7959d9c0f ("mt76: mt7663: introduce coredump support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index f2dd56674acb..d2ef2b33e2b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -2352,8 +2352,10 @@ void mt7615_coredump_work(struct work_struct *work) break; skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); - if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) - break; + if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { + dev_kfree_skb(skb); + continue; + } memcpy(data, skb->data, skb->len); data += skb->len; From 461e3b7f45766f38eeb24ca7354ff01d993b5b47 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 22 Feb 2021 02:12:09 +0100 Subject: [PATCH 029/188] mt76: mt7921: fix aggr length histogram Fix register definitions for 802.11 aggr length histogram estimation. Fixes: 474a9f21e2e2 ("mt76: mt7921: add debugfs support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c | 5 ++--- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 4bc3dd99bd14..b2e8d698e019 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -44,14 +44,13 @@ mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy, range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i)); for (i = 0; i < ARRAY_SIZE(bound); i++) - bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1; + bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; seq_printf(file, "\nPhy0\n"); seq_printf(file, "Length: %8d | ", bound[0]); for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) - seq_printf(file, "%3d -%3d | ", - bound[i] + 1, bound[i + 1]); + seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]); seq_puts(file, "\nCount: "); for (i = 0; i < ARRAY_SIZE(bound); i++) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 18980bb32dee..d7e316eb006c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -128,9 +128,9 @@ #define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) #define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) -#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2)) -#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2)) -#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2)) +#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2)) +#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2)) +#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2)) #define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) #define MT_WTBLON_TOP_BASE 0x34000 From 9fb9d755fae20b5ad62ef8b4e9289e5baea2c6fc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 22 Feb 2021 02:14:36 +0100 Subject: [PATCH 030/188] mt76: mt7915: fix aggr len debugfs node Similar to mt7921, fix 802.11 aggr len debugfs reporting for mt7915 driver. Fixes: e57b7901469fc ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 77dcd71e49a5..2f706620686e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -124,7 +124,7 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i)); for (i = 0; i < ARRAY_SIZE(bound); i++) - bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1; + bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; seq_printf(file, "\nPhy %d\n", ext_phy); From 8e84836283f18c8a408c422794a9d4ec1412f3c6 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 22 Feb 2021 17:03:31 +0800 Subject: [PATCH 031/188] mt76: mt7921: remove unneeded semicolon Fix the following coccicheck warnings: ./drivers/net/wireless/mediatek/mt76/mt7921/mac.c:1402:2-3: Unneeded semicolon. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 76d5f194706f..7faecacd5e07 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1400,7 +1400,7 @@ void mt7921_mac_work(struct work_struct *work) if (++phy->sta_work_count == 10) { phy->sta_work_count = 0; mt7921_mac_sta_stats_work(phy); - }; + } mt7921_mutex_release(phy->dev); From f76e9019913bffee0e49b096068e6f6b12f9b0e0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 22 Feb 2021 19:17:49 +0100 Subject: [PATCH 032/188] mt76: mt7921: fix stats register definitions Fix register definitions for mac80211 stats reporting. Move mib counter reset to mt7921_get_stats routine. Fixes: 163f4d22c118d ("mt76: mt7921: add MAC support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mac.c | 31 ++++++------------- .../net/wireless/mediatek/mt76/mt7921/main.c | 6 ++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 10 +++--- .../net/wireless/mediatek/mt76/mt7921/regs.h | 15 ++++++--- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 7faecacd5e07..3e96bcfda45b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1318,31 +1318,20 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy) struct mib_stats *mib = &phy->mib; int i, aggr0 = 0, aggr1; - memset(mib, 0, sizeof(*mib)); - - mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(0), - MT_MIB_SDR3_FCS_ERR_MASK); + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0), + MT_MIB_SDR3_FCS_ERR_MASK); + mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0), + MT_MIB_ACK_FAIL_COUNT_MASK); + mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0), + MT_MIB_BA_FAIL_COUNT_MASK); + mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0), + MT_MIB_RTS_COUNT_MASK); + mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0), + MT_MIB_RTS_FAIL_COUNT_MASK); for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { u32 val, val2; - val = mt76_rr(dev, MT_MIB_MB_SDR1(0, i)); - - val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); - if (val2 > mib->ack_fail_cnt) - mib->ack_fail_cnt = val2; - - val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); - if (val2 > mib->ba_miss_cnt) - mib->ba_miss_cnt = val2; - - val = mt76_rr(dev, MT_MIB_MB_SDR0(0, i)); - val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (val2 > mib->rts_retries_cnt) { - mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - mib->rts_retries_cnt = val2; - } - val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index f7552f5201b4..cdb474ff370a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -831,11 +831,17 @@ mt7921_get_stats(struct ieee80211_hw *hw, struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mib_stats *mib = &phy->mib; + mt7921_mutex_acquire(phy->dev); + stats->dot11RTSSuccessCount = mib->rts_cnt; stats->dot11RTSFailureCount = mib->rts_retries_cnt; stats->dot11FCSErrorCount = mib->fcs_err_cnt; stats->dot11ACKFailureCount = mib->ack_fail_cnt; + memset(mib, 0, sizeof(*mib)); + + mt7921_mutex_release(phy->dev); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 46e6aeec35ae..2979d06ee0ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -102,11 +102,11 @@ struct mt7921_vif { }; struct mib_stats { - u16 ack_fail_cnt; - u16 fcs_err_cnt; - u16 rts_cnt; - u16 rts_retries_cnt; - u16 ba_miss_cnt; + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; + u32 ba_miss_cnt; }; struct mt7921_phy { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index d7e316eb006c..5cab39c9e7a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -96,8 +96,8 @@ #define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800) #define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) -#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014) -#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0) +#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) +#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) #define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c) #define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) @@ -121,9 +121,14 @@ #define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) #define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, 0x104 + ((n) << 4)) -#define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16) +#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688) +#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690) +#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518) +#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520) +#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0) #define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) #define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) From a4a5a430b076860691e95337787bc666c8ab28ff Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 23 Feb 2021 16:43:11 +0800 Subject: [PATCH 033/188] mt76: mt7615: fix TSF configuration The index of TSF counters should follow HWBSSID. Fixes: d8d59f66d136 ("mt76: mt7615: support 16 interfaces") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 6 +++++- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 16 ++++++++++++++-- drivers/net/wireless/mediatek/mt76/mt7615/regs.h | 7 ++++--- .../net/wireless/mediatek/mt76/mt7615/usb_sdio.c | 6 +++++- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index d2ef2b33e2b5..0af4a5d1a64f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1005,6 +1005,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct mt7615_dev *dev = phy->dev; struct mt7615_rate_desc rd; u32 w5, w27, addr; + u16 idx = sta->vif->mt76.omac_idx; if (!mt76_is_mmio(&dev->mt76)) { mt7615_mac_queue_rate_update(phy, sta, probe_rate, rates); @@ -1056,7 +1057,10 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, mt76_wr(dev, addr + 27 * 4, w27); - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); + + mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */ sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0); sta->rate_set_tsf |= rd.rateset; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 1cf40f85eb55..68accb37ea28 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -818,15 +818,21 @@ mt7615_get_stats(struct ieee80211_hw *hw, static u64 mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_dev *dev = mt7615_hw_dev(hw); union { u64 t64; u32 t32[2]; } tsf; + u16 idx = mvif->mt76.omac_idx; + u32 reg; + + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); mt7615_mutex_acquire(dev); - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + mt76_set(dev, reg, MT_LPON_TCR_MODE); /* TSF read */ tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0); tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1); @@ -839,18 +845,24 @@ static void mt7615_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 timestamp) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_dev *dev = mt7615_hw_dev(hw); union { u64 t64; u32 t32[2]; } tsf = { .t64 = timestamp, }; + u16 idx = mvif->mt76.omac_idx; + u32 reg; + + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); mt7615_mutex_acquire(dev); mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]); mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]); /* TSF software overwrite */ - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_WRITE); + mt76_set(dev, reg, MT_LPON_TCR_WRITE); mt7615_mutex_release(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 1fd7f183629e..190a02670795 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -449,9 +449,10 @@ enum mt7615_reg_base { #define MT_LPON(_n) ((dev)->reg_map[MT_LPON_BASE] + (_n)) -#define MT_LPON_T0CR MT_LPON(0x010) -#define MT_LPON_T0CR_MODE GENMASK(1, 0) -#define MT_LPON_T0CR_WRITE BIT(0) +#define MT_LPON_TCR0(_n) MT_LPON(0x010 + ((_n) * 4)) +#define MT_LPON_TCR2(_n) MT_LPON(0x0f8 + ((_n) - 2) * 4) +#define MT_LPON_TCR_MODE GENMASK(1, 0) +#define MT_LPON_TCR_WRITE BIT(0) #define MT_LPON_UTTR0 MT_LPON(0x018) #define MT_LPON_UTTR1 MT_LPON(0x01c) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c index 203256862dfd..4a370b9f7a17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -67,6 +67,7 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, struct mt7615_rate_desc *rate = &wrd->rate; struct mt7615_sta *sta = wrd->sta; u32 w5, w27, addr, val; + u16 idx = sta->vif->mt76.omac_idx; lockdep_assert_held(&dev->mt76.mutex); @@ -118,7 +119,10 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, sta->rate_probe = sta->rateset[rate->rateset].probe_rate.idx != -1; - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); + + mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */ val = mt76_rr(dev, MT_LPON_UTTR0); sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset; From d43c7301d3308828220ad733043e53254fb98cd7 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 23 Feb 2021 16:43:12 +0800 Subject: [PATCH 034/188] mt76: mt7615: remove hdr->fw_ver check Only mt7615 uses v1 version. Also, some of released firmware doesn't have hdr->fw_ver. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 393ce09d3956..65c6ab14fe6f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1449,8 +1449,7 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) sizeof(dev->mt76.hw->wiphy->fw_version), "%.10s-%.15s", hdr->fw_ver, hdr->build_date); - if (!is_mt7615(&dev->mt76) && - !strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) { + if (!is_mt7615(&dev->mt76)) { dev->fw_ver = MT7615_FIRMWARE_V2; dev->mcu_ops = &sta_update_ops; } else { From 2eb6f6c437745bce46bd7a8f3a22a732d5b9becb Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 23 Feb 2021 11:42:49 +0100 Subject: [PATCH 035/188] mt76: mt7615: fix mib stats counter reporting to mac80211 In order to properly report MIB counters to mac80211, resets stats in mt7615_get_stats routine and hold mt76 mutex accessing MIB counters. Sum up MIB counters in mt7615_mac_update_mib_stats routine. Fixes: c388d8584bc83 ("mt76: mt7615: add a get_stats() callback") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mac.c | 26 ++++++------------- .../net/wireless/mediatek/mt76/mt7615/main.c | 6 +++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 10 +++---- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 0af4a5d1a64f..d49a3f1c6e16 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1873,10 +1873,8 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy) int i, aggr; u32 val, val2; - memset(mib, 0, sizeof(*mib)); - - mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), - MT_MIB_SDR3_FCS_ERR_MASK); + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); val = mt76_get_field(dev, MT_MIB_SDR14(ext_phy), MT_MIB_AMPDU_MPDU_COUNT); @@ -1889,24 +1887,16 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy) aggr = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; for (i = 0; i < 4; i++) { val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i)); - - val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); - if (val2 > mib->ack_fail_cnt) - mib->ack_fail_cnt = val2; - - val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); - if (val2 > mib->ba_miss_cnt) - mib->ba_miss_cnt = val2; + mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); + mib->ack_fail_cnt += FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, + val); val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); - val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (val2 > mib->rts_retries_cnt) { - mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - mib->rts_retries_cnt = val2; - } + mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); + mib->rts_retries_cnt += FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, + val); val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); - dev->mt76.aggr_stats[aggr++] += val & 0xffff; dev->mt76.aggr_stats[aggr++] += val >> 16; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 68accb37ea28..2380854ce386 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -807,11 +807,17 @@ mt7615_get_stats(struct ieee80211_hw *hw, struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mib_stats *mib = &phy->mib; + mt7615_mutex_acquire(phy->dev); + stats->dot11RTSSuccessCount = mib->rts_cnt; stats->dot11RTSFailureCount = mib->rts_retries_cnt; stats->dot11FCSErrorCount = mib->fcs_err_cnt; stats->dot11ACKFailureCount = mib->ack_fail_cnt; + memset(mib, 0, sizeof(*mib)); + + mt7615_mutex_release(phy->dev); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index aa6fe65f42a7..84d06f2b41d4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -133,11 +133,11 @@ struct mt7615_vif { }; struct mib_stats { - u16 ack_fail_cnt; - u16 fcs_err_cnt; - u16 rts_cnt; - u16 rts_retries_cnt; - u16 ba_miss_cnt; + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; + u32 ba_miss_cnt; unsigned long aggr_per; }; From 2b35050a321865859fd2f12a3c18ed7be27858c9 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 23 Feb 2021 22:00:36 +0800 Subject: [PATCH 036/188] mt76: mt7915: fix mib stats counter reporting to mac80211 In order to properly report MIB counters to mac80211, resets stats in mt7915_get_stats routine() and hold mt76 mutex accessing MIB counters. Sum up MIB counters in mt7915_mac_update_mib_stats routine. Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/mac.c | 35 +++++++------------ .../net/wireless/mediatek/mt76/mt7915/main.c | 6 ++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 10 +++--- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index b5a41cb7fbda..2a3c7b39d2ca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1678,39 +1678,30 @@ mt7915_mac_update_mib_stats(struct mt7915_phy *phy) bool ext_phy = phy != &dev->phy; int i, aggr0, aggr1; - memset(mib, 0, sizeof(*mib)); - - mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), - MT_MIB_SDR3_FCS_ERR_MASK); + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { - u32 val, val2; + u32 val; val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i)); - - val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); - if (val2 > mib->ack_fail_cnt) - mib->ack_fail_cnt = val2; - - val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); - if (val2 > mib->ba_miss_cnt) - mib->ba_miss_cnt = val2; + mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); + mib->ack_fail_cnt += + FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); - val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (val2 > mib->rts_retries_cnt) { - mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - mib->rts_retries_cnt = val2; - } + mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); + mib->rts_retries_cnt += + FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); - val2 = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); - dev->mt76.aggr_stats[aggr0++] += val & 0xffff; dev->mt76.aggr_stats[aggr0++] += val >> 16; - dev->mt76.aggr_stats[aggr1++] += val2 & 0xffff; - dev->mt76.aggr_stats[aggr1++] += val2 >> 16; + + val = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); + dev->mt76.aggr_stats[aggr1++] += val & 0xffff; + dev->mt76.aggr_stats[aggr1++] += val >> 16; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 2406733f542d..cacc9b6933ca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -717,13 +717,19 @@ mt7915_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mib_stats *mib = &phy->mib; + mutex_lock(&dev->mt76.mutex); stats->dot11RTSSuccessCount = mib->rts_cnt; stats->dot11RTSFailureCount = mib->rts_retries_cnt; stats->dot11FCSErrorCount = mib->fcs_err_cnt; stats->dot11ACKFailureCount = mib->ack_fail_cnt; + memset(mib, 0, sizeof(*mib)); + + mutex_unlock(&dev->mt76.mutex); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 5c7eefdf2013..1160d1bf8a7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -108,11 +108,11 @@ struct mt7915_vif { }; struct mib_stats { - u16 ack_fail_cnt; - u16 fcs_err_cnt; - u16 rts_cnt; - u16 rts_retries_cnt; - u16 ba_miss_cnt; + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; + u32 ba_miss_cnt; }; struct mt7915_hif { From c996f0346e40e3b1ac2ebaf0681df898fb157f60 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 23 Feb 2021 18:28:43 +0100 Subject: [PATCH 037/188] mt76: connac: fix kernel warning adding monitor interface Fix the following kernel warning adding a monitor interface in mt76_connac_mcu_uni_add_dev routine. [ 507.984882] ------------[ cut here ]------------ [ 507.989515] WARNING: CPU: 1 PID: 3017 at mt76_connac_mcu_uni_add_dev+0x178/0x190 [mt76_connac_lib] [ 508.059379] CPU: 1 PID: 3017 Comm: ifconfig Not tainted 5.4.98 #0 [ 508.065461] Hardware name: MT7622_MT7531 RFB (DT) [ 508.070156] pstate: 80000005 (Nzcv daif -PAN -UAO) [ 508.074939] pc : mt76_connac_mcu_uni_add_dev+0x178/0x190 [mt76_connac_lib] [ 508.081806] lr : mt7921_eeprom_init+0x1288/0x1cb8 [mt7921e] [ 508.087367] sp : ffffffc013a33930 [ 508.090671] x29: ffffffc013a33930 x28: ffffff801e628ac0 [ 508.095973] x27: ffffff801c7f1200 x26: ffffff801c7eb008 [ 508.101275] x25: ffffff801c7eaef0 x24: ffffff801d025610 [ 508.106577] x23: ffffff801d022990 x22: ffffff801d024de8 [ 508.111879] x21: ffffff801d0226a0 x20: ffffff801c7eaee8 [ 508.117181] x19: ffffff801d0226a0 x18: 000000005d00b000 [ 508.122482] x17: 00000000ffffffff x16: 0000000000000000 [ 508.127785] x15: 0000000000000080 x14: ffffff801d704000 [ 508.133087] x13: 0000000000000040 x12: 0000000000000002 [ 508.138389] x11: 000000000000000c x10: 0000000000000000 [ 508.143691] x9 : 0000000000000020 x8 : 0000000000000001 [ 508.148992] x7 : 0000000000000000 x6 : 0000000000000000 [ 508.154294] x5 : ffffff801c7eaee8 x4 : 0000000000000006 [ 508.159596] x3 : 0000000000000001 x2 : 0000000000000000 [ 508.164898] x1 : ffffff801c7eac08 x0 : ffffff801d0226a0 [ 508.170200] Call trace: [ 508.172640] mt76_connac_mcu_uni_add_dev+0x178/0x190 [mt76_connac_lib] [ 508.179159] mt7921_eeprom_init+0x1288/0x1cb8 [mt7921e] [ 508.184394] drv_add_interface+0x34/0x88 [mac80211] [ 508.189271] ieee80211_add_virtual_monitor+0xe0/0xb48 [mac80211] [ 508.195277] ieee80211_do_open+0x86c/0x918 [mac80211] [ 508.200328] ieee80211_do_open+0x900/0x918 [mac80211] [ 508.205372] __dev_open+0xcc/0x150 [ 508.208763] __dev_change_flags+0x134/0x198 [ 508.212937] dev_change_flags+0x20/0x60 [ 508.216764] devinet_ioctl+0x3e8/0x748 [ 508.220503] inet_ioctl+0x1e4/0x350 [ 508.223983] sock_do_ioctl+0x48/0x2a0 [ 508.227635] sock_ioctl+0x310/0x4f8 [ 508.231116] do_vfs_ioctl+0xa4/0xac0 [ 508.234681] ksys_ioctl+0x44/0x90 [ 508.237985] __arm64_sys_ioctl+0x1c/0x48 [ 508.241901] el0_svc_common.constprop.1+0x7c/0x100 [ 508.246681] el0_svc_handler+0x18/0x20 [ 508.250421] el0_svc+0x8/0x1c8 [ 508.253465] ---[ end trace c7b90fee13d72c39 ]--- [ 508.261278] ------------[ cut here ]------------ Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index ab9e48c19508..2cd1677d881e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -968,6 +968,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP: basic_req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); break; From 57b8b57516c5108b0078051a31c68dc9dfcbf68f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Feb 2021 12:29:34 +0100 Subject: [PATCH 038/188] mt76: check return value of mt76_txq_send_burst in mt76_txq_schedule_list Since mt76_txq_send_burst routine can report a negative error code, check the returned value before incrementing the number of transmitted frames in mt76_txq_schedule_list routine. Return -EBUSY directly if the device is in reset or in power management. Fixes: 90fdc1717b186 ("mt76: use mac80211 txq scheduling") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/tx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index b8fe8adc43a3..451ed60c6296 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -461,11 +461,11 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) int ret = 0; while (1) { + int n_frames = 0; + if (test_bit(MT76_STATE_PM, &phy->state) || - test_bit(MT76_RESET, &phy->state)) { - ret = -EBUSY; - break; - } + test_bit(MT76_RESET, &phy->state)) + return -EBUSY; if (dev->queue_ops->tx_cleanup && q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) { @@ -497,11 +497,16 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) } if (!mt76_txq_stopped(q)) - ret += mt76_txq_send_burst(phy, q, mtxq); + n_frames = mt76_txq_send_burst(phy, q, mtxq); spin_unlock_bh(&q->lock); ieee80211_return_txq(phy->hw, txq, false); + + if (unlikely(n_frames < 0)) + return n_frames; + + ret += n_frames; } return ret; From 3ab0269d75cd4800750f7e3e1b037db144f9d034 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Feb 2021 16:57:18 +0100 Subject: [PATCH 039/188] mt76: mt7921: get rid of mt7921_sta_rc_update routine Since the rate selection is currently managed by the fw, get rid of empty mt7921_sta_rc_update routine Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index cdb474ff370a..43e878c69616 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1031,14 +1031,6 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) return 0; } -static void -mt7921_sta_rc_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - u32 changed) -{ -} - static void mt7921_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1165,7 +1157,6 @@ const struct ieee80211_ops mt7921_ops = { .sta_add = mt7921_sta_add, .sta_remove = mt7921_sta_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, - .sta_rc_update = mt7921_sta_rc_update, .set_key = mt7921_set_key, .ampdu_action = mt7921_ampdu_action, .set_rts_threshold = mt7921_set_rts_threshold, From 23c1d2dc9ed5be1d0df7987335f5646e3826a461 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 26 Feb 2021 16:23:26 +0800 Subject: [PATCH 040/188] mt76: mt7921: fix the base of PCIe interrupt Should use 0x10000 as the base to operate PCIe interrupt according to the vendor reference driver. Fixes: ffa1bf97425b ("mt76: mt7921: introduce PM support") Co-developed-by: YN Chen Signed-off-by: YN Chen Signed-off-by: Sean Wang Tested-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 7e040c38c3b7..e94523bf19be 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -137,7 +137,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); - mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); @@ -248,7 +248,7 @@ static int mt7921_pci_resume(struct pci_dev *pdev) return err; /* enable interrupt */ - mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | MT_INT_MCU_CMD); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 5cab39c9e7a2..6754b10f9a6b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -389,7 +389,7 @@ #define MT_HW_CHIPID 0x70010200 #define MT_HW_REV 0x70010204 -#define MT_PCIE_MAC_BASE 0x74030000 +#define MT_PCIE_MAC_BASE 0x10000 #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) From 53a8fb4afdc877f8f2d5e1e15cc5ad66155987a6 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 26 Feb 2021 16:23:27 +0800 Subject: [PATCH 041/188] mt76: mt7921: fix the base of the dynamic remap We should change the base for the dynamic remap into another one, because the current base (0xe0000) have been the one used to operate the device ownership. Fixes: 163f4d22c118 ("mt76: mt7921: add MAC support") Co-developed-by: YN Chen Signed-off-by: YN Chen Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 6754b10f9a6b..b66e15c8ab70 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -362,11 +362,11 @@ #define MT_INFRA_CFG_BASE 0xfe000 #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) -#define MT_HIF_REMAP_L1 MT_INFRA(0x260) +#define MT_HIF_REMAP_L1 MT_INFRA(0x24c) #define MT_HIF_REMAP_L1_MASK GENMASK(15, 0) #define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0) #define MT_HIF_REMAP_L1_BASE GENMASK(31, 16) -#define MT_HIF_REMAP_BASE_L1 0xe0000 +#define MT_HIF_REMAP_BASE_L1 0x40000 #define MT_SWDEF_BASE 0x41f200 #define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) From f92f81d35ac26f8a519866f1b561743fe70e33a5 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 26 Feb 2021 12:17:23 +0100 Subject: [PATCH 042/188] mt76: mt7921: check mcu returned values in mt7921_start Properly check returned values from mcu utility routines in mt7921_start. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 43e878c69616..043dd77bdbe7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -173,22 +173,31 @@ static int mt7921_start(struct ieee80211_hw *hw) { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); + int err; mt7921_mutex_acquire(dev); - mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); - mt76_connac_mcu_set_channel_domain(phy->mt76); + err = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); + if (err) + goto out; + + err = mt76_connac_mcu_set_channel_domain(phy->mt76); + if (err) + goto out; + + err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + if (err) + goto out; - mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); mt7921_mac_reset_counters(phy); set_bit(MT76_STATE_RUNNING, &phy->mt76->state); ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, MT7921_WATCHDOG_TIME); - +out: mt7921_mutex_release(dev); - return 0; + return err; } static void mt7921_stop(struct ieee80211_hw *hw) From e268fcaa67b855af41c5eb4c641288a2bef05b17 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 27 Feb 2021 00:44:27 +0800 Subject: [PATCH 043/188] mt76: mt7915: add missing capabilities for DBDC This improves dbdc performance. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/init.c | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index c599b44a728c..165be6abcc96 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -113,6 +113,24 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, WANT_MONITOR_VIF); hw->max_tx_fragments = 4; + + if (phy->mt76->cap.has_2ghz) + phy->mt76->sband_2g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + + if (phy->mt76->cap.has_5ghz) { + phy->mt76->sband_5g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + } + + mt76_set_stream_caps(phy->mt76, true); + mt7915_set_stream_vht_txbf_caps(phy); + mt7915_set_stream_he_caps(phy); } static void @@ -240,22 +258,17 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev) phy->mt76 = mphy; mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1; - mt7915_init_wiphy(mphy->hw); INIT_LIST_HEAD(&phy->stats_list); INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work); mt7915_eeprom_parse_band_config(phy); - mt7915_set_stream_vht_txbf_caps(phy); - mt7915_set_stream_he_caps(phy); + mt7915_init_wiphy(mphy->hw); memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2, ETH_ALEN); mt76_eeprom_override(mphy); - /* The second interface does not get any packets unless it has a vif */ - ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); - ret = mt7915_init_tx_queues(phy, MT7915_TXQ_BAND1, MT7915_TX_RING_SIZE); if (ret) @@ -332,8 +345,14 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy) { - int nss = hweight8(phy->mt76->chainmask); - u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap; + int nss; + u32 *cap; + + if (!phy->mt76->cap.has_5ghz) + return; + + nss = hweight8(phy->mt76->chainmask); + cap = &phy->mt76->sband_5g.sband.vht_cap.cap; *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | @@ -637,25 +656,14 @@ int mt7915_register_device(struct mt7915_dev *dev) return ret; mt7915_init_wiphy(hw); - dev->mphy.sband_2g.sband.ht_cap.cap |= - IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_MAX_AMSDU; - dev->mphy.sband_5g.sband.ht_cap.cap |= - 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_A_MPDU_LENGTH_EXPONENT_MASK; + if (!dev->dbdc_support) dev->mphy.sband_5g.sband.vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; - - mt76_set_stream_caps(&dev->mphy, true); - mt7915_set_stream_vht_txbf_caps(&dev->phy); - mt7915_set_stream_he_caps(&dev->phy); dev->phy.dfs_state = -1; #ifdef CONFIG_NL80211_TESTMODE From 402a695b1ae69b1cc2e445b2258841fd39f92780 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 27 Feb 2021 15:39:42 +0800 Subject: [PATCH 044/188] mt76: mt7615: fix CSA notification for DBDC Add CSA notification for second phy. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 25 +++++++++++++++---- .../net/wireless/mediatek/mt76/mt7615/mcu.h | 10 +++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 65c6ab14fe6f..4ca0d8d4c536 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -372,6 +372,23 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) ieee80211_csa_finish(vif); } +static void +mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_phy *ext_phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_mcu_csa_notify *c; + + c = (struct mt7615_mcu_csa_notify *)skb->data; + + if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx)) + mphy = dev->mt76.phy2; + + ieee80211_iterate_active_interfaces_atomic(mphy->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_mcu_csa_finish, mphy->hw); +} + static void mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) { @@ -380,7 +397,7 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) r = (struct mt7615_mcu_rdd_report *)skb->data; - if (r->idx && dev->mt76.phy2) + if (r->band_idx && dev->mt76.phy2) mphy = dev->mt76.phy2; ieee80211_radar_detected(mphy->hw); @@ -419,9 +436,7 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) mt7615_mcu_rx_radar_detected(dev, skb); break; case MCU_EXT_EVENT_CSA_NOTIFY: - ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7615_mcu_csa_finish, dev); + mt7615_mcu_rx_csa_notify(dev, skb); break; case MCU_EXT_EVENT_FW_LOG_2_HOST: mt7615_mcu_rx_log_message(dev, skb); @@ -2176,7 +2191,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 411ebb56baef..98c383e400a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -176,10 +176,18 @@ struct mt7615_mcu_rxd { u8 s2d_index; }; +struct mt7615_mcu_csa_notify { + struct mt7615_mcu_rxd rxd; + + u8 omac_idx; + u8 csa_count; + u8 rsv[2]; +} __packed; + struct mt7615_mcu_rdd_report { struct mt7615_mcu_rxd rxd; - u8 idx; + u8 band_idx; u8 long_detected; u8 constant_prf_detected; u8 staggered_prf_detected; From 62da7a38e04131178e1344f080a7d02f76f9c149 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 27 Feb 2021 15:39:43 +0800 Subject: [PATCH 045/188] mt76: mt7615: stop ext_phy queue when mac reset happens Stop Tx burst for ext_phy after mac reset. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index d49a3f1c6e16..59aa8f84645b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -2075,6 +2075,7 @@ void mt7615_mac_reset_work(struct work_struct *work) del_timer_sync(&dev->phy.roc_timer); cancel_work_sync(&dev->phy.roc_work); if (phy2) { + set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); del_timer_sync(&phy2->roc_timer); cancel_work_sync(&phy2->roc_work); @@ -2108,6 +2109,8 @@ void mt7615_mac_reset_work(struct work_struct *work) clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); + if (phy2) + clear_bit(MT76_RESET, &phy2->mt76->state); mt76_worker_enable(&dev->mt76.tx_worker); napi_enable(&dev->mt76.tx_napi); From b6d20ce433c97fa995d7ec067e642cfdf02c0aac Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 27 Feb 2021 15:39:44 +0800 Subject: [PATCH 046/188] mt76: mt7915: fix CSA notification for DBDC Add CSA notification for second phy. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 24 +++++++++++++++---- .../net/wireless/mediatek/mt76/mt7915/mcu.h | 11 ++++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 6c429a2b15c5..4abe32357edc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -336,6 +336,22 @@ mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) ieee80211_csa_finish(vif); } +static void +mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7915_mcu_csa_notify *c; + + c = (struct mt7915_mcu_csa_notify *)skb->data; + + if (c->band_idx && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ieee80211_iterate_active_interfaces_atomic(mphy->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7915_mcu_csa_finish, mphy->hw); +} + static void mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) { @@ -344,7 +360,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) r = (struct mt7915_mcu_rdd_report *)skb->data; - if (r->idx && dev->mt76.phy2) + if (r->band_idx && dev->mt76.phy2) mphy = dev->mt76.phy2; ieee80211_radar_detected(mphy->hw); @@ -511,9 +527,7 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) mt7915_mcu_rx_radar_detected(dev, skb); break; case MCU_EXT_EVENT_CSA_NOTIFY: - ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7915_mcu_csa_finish, dev); + mt7915_mcu_rx_csa_notify(dev, skb); break; case MCU_EXT_EVENT_RATE_REPORT: mt7915_mcu_tx_rate_report(dev, skb); @@ -3219,7 +3233,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) } #endif - if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 2a2f7bf2c94b..4a932140a7c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -68,10 +68,19 @@ struct mt7915_mcu_rxd { u8 s2d_index; }; +struct mt7915_mcu_csa_notify { + struct mt7915_mcu_rxd rxd; + + u8 omac_idx; + u8 csa_count; + u8 band_idx; + u8 rsv; +} __packed; + struct mt7915_mcu_rdd_report { struct mt7915_mcu_rxd rxd; - u8 idx; + u8 band_idx; u8 long_detected; u8 constant_prf_detected; u8 staggered_prf_detected; From 6636539283780a0c34880e43a2f4ada561509f61 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 27 Feb 2021 15:39:45 +0800 Subject: [PATCH 047/188] mt76: mt7915: stop ext_phy queue when mac reset happens Stop Tx burst for ext_phy after mac reset. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 2a3c7b39d2ca..d3a6312c058c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1607,9 +1607,10 @@ void mt7915_mac_reset_work(struct work_struct *work) set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->mphy.mac_work); - if (phy2) + if (phy2) { + set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); - + } /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); if (ext_phy) @@ -1637,6 +1638,8 @@ void mt7915_mac_reset_work(struct work_struct *work) clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); + if (phy2) + clear_bit(MT76_RESET, &phy2->mt76->state); mt76_worker_enable(&dev->mt76.tx_worker); napi_enable(&dev->mt76.tx_napi); From 1623474167f83252576c90b1df42292c6a99ccb7 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 27 Feb 2021 15:39:46 +0800 Subject: [PATCH 048/188] mt76: mt7915: fix PHY mode for DBDC Fix PHY mode configuration for DBDC. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 4abe32357edc..e0c03b7f278d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -147,9 +147,10 @@ mt7915_get_he_phy_cap(struct mt7915_phy *phy, struct ieee80211_vif *vif) } static u8 -mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, - enum nl80211_band band, struct ieee80211_sta *sta) +mt7915_get_phy_mode(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { + enum nl80211_band band = mphy->chandef.chan->band; struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_vht_cap *vht_cap; const struct ieee80211_sta_he_cap *he_cap; @@ -161,12 +162,8 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, he_cap = &sta->he_cap; } else { struct ieee80211_supported_band *sband; - struct mt7915_phy *phy; - struct mt7915_vif *mvif; - mvif = (struct mt7915_vif *)vif->drv_priv; - phy = mvif->band_idx ? mt7915_ext_phy(dev) : &dev->phy; - sband = phy->mt76->hw->wiphy->bands[band]; + sband = mphy->hw->wiphy->bands[band]; ht_cap = &sband->ht_cap; vht_cap = &sband->vht_cap; @@ -676,8 +673,6 @@ mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7915_phy *phy, bool enable) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct cfg80211_chan_def *chandef = &phy->mt76->chandef; - enum nl80211_band band = chandef->chan->band; struct bss_info_basic *bss; u16 wlan_idx = mvif->sta.wcid.idx; u32 type = NETWORK_INFRA; @@ -727,7 +722,7 @@ mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); bss->dtim_period = vif->bss_conf.dtim_period; - bss->phy_mode = mt7915_get_phy_mode(phy->dev, vif, band, NULL); + bss->phy_mode = mt7915_get_phy_mode(phy->mt76, vif, NULL); } else { memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN); } @@ -2069,25 +2064,30 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif, static void mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt76_phy *mphy = &dev->mphy; + enum nl80211_band band; struct sta_rec_ra *ra; struct tlv *tlv; - enum nl80211_band band = chandef->chan->band; - u32 supp_rate = sta->supp_rates[band]; - int n_rates = hweight32(supp_rate); - u32 cap = sta->wme ? STA_CAP_WMM : 0; + u32 supp_rate, n_rates, cap = sta->wme ? STA_CAP_WMM : 0; u8 i, nss = sta->rx_nss, mcs = 0; tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); - ra = (struct sta_rec_ra *)tlv; + + if (msta->wcid.ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + band = mphy->chandef.chan->band; + supp_rate = sta->supp_rates[band]; + n_rates = hweight32(supp_rate); + ra->valid = true; ra->auto_rate = true; - ra->phy_mode = mt7915_get_phy_mode(dev, vif, band, sta); - ra->channel = chandef->chan->hw_value; + ra->phy_mode = mt7915_get_phy_mode(mphy, vif, sta); + ra->channel = mphy->chandef.chan->hw_value; ra->bw = sta->bandwidth; ra->rate_len = n_rates; ra->phy.bw = sta->bandwidth; From 51bf9d60fb927b850ec2abdc1f9f72de523098a3 Mon Sep 17 00:00:00 2001 From: "Eric Y.Y. Wong" Date: Wed, 3 Mar 2021 11:43:52 +0800 Subject: [PATCH 049/188] mt76: mt76x0u: Add support for TP-Link T2UHP(UN) v1 There are two variants of TP-Link Archer T2UHP V1, which are US and UN: https://www.tp-link.com/us/support/download/archer-t2uhp/ https://www.tp-link.com/hk/support/download/archer-t2uhp/v1/ From the driver source code provided by the vendor: https://www.tp-link.com/hk/support/download/archer-t2uhp/v1/#Driver eric@eric-VirtualBox:~/src$ grep -n USB_DEVICE.*0x2357 DPA_mt7610u_wifi_sta_v3004_rev1_20140529/NETIF/common/rtusb_dev_id.c 45: {USB_DEVICE(0x2357,0x0105)}, /* T1Uv1 */ 46: {USB_DEVICE(0x2357,0x010B)}, /* T2UHP_UN_v1 */ 47: {USB_DEVICE(0x2357,0x0123)}, /* T2UHP_US_v1 */ eric@eric-VirtualBox:~/src$ lsusb -d 2357: Bus 001 Device 003: ID 2357:010b TP-Link WiFi eric@eric-VirtualBox:~/src$ sudo modprobe mt76x0u eric@eric-VirtualBox:~/src$ sudo sh -c "echo 2357 010b > /sys/bus/usb/drivers/mt76x0u/new_id" [snip] eric@eric-VirtualBox:~/src$ ifconfig -a enp0s3: flags=4163 mtu 1500 ether 08:00:27:74:d9:ee txqueuelen 1000 (Ethernet) RX packets 78 bytes 16146 (16.1 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 75 bytes 8413 (8.4 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 56 bytes 5496 (5.4 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 56 bytes 5496 (5.4 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 wlx18d6c71b6e3e: flags=4163 mtu 1500 inet 192.168.1.106 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::21c7:2d90:e47d:ee48 prefixlen 64 scopeid 0x20 ether 18:d6:c7:1b:6e:3e txqueuelen 1000 (Ethernet) RX packets 37 bytes 5345 (5.3 KB) RX errors 0 dropped 7 overruns 0 frame 0 TX packets 77 bytes 10513 (10.5 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eric@eric-VirtualBox:~/src$ dmesg | tail -n 30 12:51:25.551584 main Log opened 2021-03-01T12:51:25.551572000Z [ 46.855763] 12:51:25.551995 main OS Product: Linux [ 46.855838] 12:51:25.552075 main OS Release: 5.4.0-66-generic [ 46.855897] 12:51:25.552150 main OS Version: #74-Ubuntu SMP Wed Jan 27 22:54:38 UTC 2021 [ 46.855971] 12:51:25.552207 main Executable: /opt/VBoxGuestAdditions-6.1.16/sbin/VBoxService 12:51:25.552208 main Process ID: 898 12:51:25.552209 main Package type: LINUX_64BITS_GENERIC [ 46.858699] 12:51:25.554921 main 6.1.16 r140961 started. Verbose level = 0 [ 46.863116] 12:51:25.559319 main vbglR3GuestCtrlDetectPeekGetCancelSupport: Supported (#1) [ 140.687550] usb 1-2: new high-speed USB device number 3 using xhci_hcd [ 140.838279] usb 1-2: New USB device found, idVendor=2357, idProduct=010b, bcdDevice= 1.00 [ 140.838281] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 140.838283] usb 1-2: Product: WiFi [ 140.838284] usb 1-2: Manufacturer: MediaTek [ 140.838285] usb 1-2: SerialNumber: 1.0 [ 178.374187] cfg80211: Loading compiled-in X.509 certificates for regulatory database [ 178.378370] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7' [ 178.417507] usbcore: registered new interface driver mt76x0u [ 178.557165] usb 1-2: reset high-speed USB device number 3 using xhci_hcd [ 178.720436] mt76x0u 1-2:1.0: ASIC revision: 76100002 MAC revision: 76502000 [ 180.156077] mt76x0u 1-2:1.0: EEPROM ver:02 fae:04 [ 181.190558] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht' [ 181.225560] mt76x0u 1-2:1.0 wlx18d6c71b6e3e: renamed from wlan0 [ 188.660826] wlx18d6c71b6e3e: authenticate with d0:17:c2:e0:d7:9c [ 189.447781] wlx18d6c71b6e3e: send auth to d0:17:c2:e0:d7:9c (try 1/3) [ 189.618282] wlx18d6c71b6e3e: authenticated [ 189.619008] wlx18d6c71b6e3e: associate with d0:17:c2:e0:d7:9c (try 1/3) [ 189.715268] wlx18d6c71b6e3e: RX AssocResp from d0:17:c2:e0:d7:9c (capab=0x1011 status=0 aid=8) [ 189.734720] wlx18d6c71b6e3e: associated [ 190.233239] IPv6: ADDRCONF(NETDEV_CHANGE): wlx18d6c71b6e3e: link becomes ready Signed-off-by: Eric Y.Y. Wong Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index a593a7796d23..f2b2fa733845 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -32,7 +32,8 @@ static struct usb_device_id mt76x0_device_table[] = { { USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH */ { USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */ { USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac Stick */ - { USB_DEVICE(0x2357, 0x0123) }, /* TP-LINK T2UHP */ + { USB_DEVICE(0x2357, 0x0123) }, /* TP-LINK T2UHP_US_v1 */ + { USB_DEVICE(0x2357, 0x010b) }, /* TP-LINK T2UHP_UN_v1 */ /* TP-LINK Archer T1U */ { USB_DEVICE(0x2357, 0x0105), .driver_info = 1, }, /* MT7630U */ From 7883906d22c1e73f1f316bd84fc4a7ff8edd12aa Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 3 Mar 2021 18:37:59 +0800 Subject: [PATCH 050/188] mt76: mt7915: fix rxrate reporting Avoid directly updating sinfo->rxrate from firmware since rate_info might be overwritten by wrong results even mt7915_mcu_get_rx_rate() fails check. Add more error handlings accordingly. Fixes: 11553d88d0b9 ("mt76: mt7915: query station rx rate from firmware") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/main.c | 5 +- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 47 ++++++++++--------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index cacc9b6933ca..bb49ea9307e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -839,9 +839,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_sta_stats *stats = &msta->stats; + struct rate_info rxrate = {}; - if (mt7915_mcu_get_rx_rate(phy, vif, sta, &sinfo->rxrate) == 0) + if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { + sinfo->rxrate = rxrate; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); + } if (!stats->tx_rate.legacy && !stats->tx_rate.flags) return; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index e0c03b7f278d..b204c5dd7914 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -3552,9 +3552,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_supported_band *sband; struct mt7915_mcu_phy_rx_info *res; struct sk_buff *skb; - u16 flags = 0; int ret; - int i; + bool cck = false; ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(PHY_STAT_INFO), &req, sizeof(req), true, &skb); @@ -3568,48 +3567,53 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, switch (res->mode) { case MT_PHY_TYPE_CCK: + cck = true; + fallthrough; case MT_PHY_TYPE_OFDM: if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; else sband = &mphy->sband_2g.sband; - for (i = 0; i < sband->n_bitrates; i++) { - if (rate->mcs != (sband->bitrates[i].hw_value & 0xf)) - continue; - - rate->legacy = sband->bitrates[i].bitrate; - break; - } + rate->mcs = mt76_get_rate(&dev->mt76, 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) - return -EINVAL; - - flags |= RATE_INFO_FLAGS_MCS; + if (rate->mcs > 31) { + ret = -EINVAL; + goto out; + } + rate->flags = RATE_INFO_FLAGS_MCS; if (res->gi) - flags |= RATE_INFO_FLAGS_SHORT_GI; + rate->flags |= RATE_INFO_FLAGS_SHORT_GI; break; case MT_PHY_TYPE_VHT: - flags |= RATE_INFO_FLAGS_VHT_MCS; + if (rate->mcs > 9) { + ret = -EINVAL; + goto out; + } + rate->flags = RATE_INFO_FLAGS_VHT_MCS; if (res->gi) - flags |= RATE_INFO_FLAGS_SHORT_GI; + rate->flags |= RATE_INFO_FLAGS_SHORT_GI; 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 (res->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11) { + ret = -EINVAL; + goto out; + } rate->he_gi = res->gi; - - flags |= RATE_INFO_FLAGS_HE_MCS; + rate->flags = RATE_INFO_FLAGS_HE_MCS; break; default: - break; + ret = -EINVAL; + goto out; } - rate->flags = flags; switch (res->bw) { case IEEE80211_STA_RX_BW_160: @@ -3626,7 +3630,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, break; } +out: dev_kfree_skb(skb); - return 0; + return ret; } From f43b941fd61003659a3f0e039595e5e525917aa8 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 3 Mar 2021 18:38:00 +0800 Subject: [PATCH 051/188] mt76: mt7915: fix txrate reporting Properly check rate_info to fix unexpected reporting. [ 1215.161863] Call trace: [ 1215.164307] cfg80211_calculate_bitrate+0x124/0x200 [cfg80211] [ 1215.170139] ieee80211s_update_metric+0x80/0xc0 [mac80211] [ 1215.175624] ieee80211_tx_status_ext+0x508/0x838 [mac80211] [ 1215.181190] mt7915_mcu_get_rx_rate+0x28c/0x8d0 [mt7915e] [ 1215.186580] mt7915_mac_tx_free+0x324/0x7c0 [mt7915e] [ 1215.191623] mt7915_queue_rx_skb+0xa8/0xd0 [mt7915e] [ 1215.196582] mt76_dma_cleanup+0x7b0/0x11d0 [mt76] [ 1215.201276] __napi_poll+0x38/0xf8 [ 1215.204668] napi_workfn+0x40/0x80 [ 1215.208062] process_one_work+0x1fc/0x390 [ 1215.212062] worker_thread+0x48/0x4d0 [ 1215.215715] kthread+0x120/0x128 [ 1215.218935] ret_from_fork+0x10/0x1c Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets") Fixes: e4c5ead632ff ("mt76: mt7915: rename mt7915_mcu_get_rate_info to mt7915_mcu_get_tx_rate") Reported-by: Evelyn Tsai Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index b204c5dd7914..29b5039cc286 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -364,54 +364,62 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) dev->hw_pattern++; } -static void +static int mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, struct rate_info *rate, u16 r) { struct ieee80211_supported_band *sband; u16 ru_idx = le16_to_cpu(ra->ru_idx); - u16 flags = 0; + bool cck = false; rate->mcs = FIELD_GET(MT_RA_RATE_MCS, r); rate->nss = FIELD_GET(MT_RA_RATE_NSS, r) + 1; switch (FIELD_GET(MT_RA_RATE_TX_MODE, r)) { case MT_PHY_TYPE_CCK: + cck = true; + fallthrough; case MT_PHY_TYPE_OFDM: if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.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: rate->mcs += (rate->nss - 1) * 8; - flags |= RATE_INFO_FLAGS_MCS; + if (rate->mcs > 31) + return -EINVAL; + rate->flags = RATE_INFO_FLAGS_MCS; if (ra->gi) - flags |= RATE_INFO_FLAGS_SHORT_GI; + rate->flags |= RATE_INFO_FLAGS_SHORT_GI; break; case MT_PHY_TYPE_VHT: - flags |= RATE_INFO_FLAGS_VHT_MCS; + if (rate->mcs > 9) + return -EINVAL; + rate->flags = RATE_INFO_FLAGS_VHT_MCS; if (ra->gi) - flags |= RATE_INFO_FLAGS_SHORT_GI; + rate->flags |= RATE_INFO_FLAGS_SHORT_GI; 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 (ra->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11) + return -EINVAL; + rate->he_gi = ra->gi; rate->he_dcm = FIELD_GET(MT_RA_RATE_DCM_EN, r); - - flags |= RATE_INFO_FLAGS_HE_MCS; + rate->flags = RATE_INFO_FLAGS_HE_MCS; break; default: - break; + return -EINVAL; } - rate->flags = flags; if (ru_idx) { switch (ru_idx) { @@ -448,6 +456,8 @@ mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, break; } } + + return 0; } static void @@ -478,12 +488,12 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb) mphy = dev->mt76.phy2; /* current rate */ - mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr); - stats->tx_rate = rate; + if (!mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr)) + stats->tx_rate = rate; /* probing rate */ - mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe); - stats->prob_rate = prob_rate; + if (!mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe)) + stats->prob_rate = prob_rate; if (attempts) { u16 success = le16_to_cpu(ra->success); From b1bed649ad0378afc01226c89d7e89f0580788ba Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 3 Mar 2021 18:38:01 +0800 Subject: [PATCH 052/188] mt76: mt7915: check mcu returned values in mt7915_ops Properly check returned values from mcu utility routines in mt7915_ops. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/main.c | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index bb49ea9307e0..255f87aa1830 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -25,6 +25,7 @@ static int mt7915_start(struct ieee80211_hw *hw) struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_phy *phy = mt7915_hw_phy(hw); bool running; + int ret; flush_work(&dev->init_work); @@ -33,21 +34,44 @@ static int mt7915_start(struct ieee80211_hw *hw) running = mt7915_dev_running(dev); if (!running) { - mt7915_mcu_set_pm(dev, 0, 0); - mt7915_mcu_set_mac(dev, 0, true, true); - mt7915_mcu_set_scs(dev, 0, true); + ret = mt7915_mcu_set_pm(dev, 0, 0); + if (ret) + goto out; + + ret = mt7915_mcu_set_mac(dev, 0, true, true); + if (ret) + goto out; + + ret = mt7915_mcu_set_scs(dev, 0, true); + if (ret) + goto out; + mt7915_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { - mt7915_mcu_set_pm(dev, 1, 0); - mt7915_mcu_set_mac(dev, 1, true, true); - mt7915_mcu_set_scs(dev, 1, true); + ret = mt7915_mcu_set_pm(dev, 1, 0); + if (ret) + goto out; + + ret = mt7915_mcu_set_mac(dev, 1, true, true); + if (ret) + goto out; + + ret = mt7915_mcu_set_scs(dev, 1, true); + if (ret) + goto out; + mt7915_mac_enable_nf(dev, 1); } - mt7915_mcu_set_sku_en(phy, true); - mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); + ret = mt7915_mcu_set_sku_en(phy, true); + if (ret) + goto out; + + ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); + if (ret) + goto out; set_bit(MT76_STATE_RUNNING, &phy->mt76->state); @@ -58,9 +82,10 @@ static int mt7915_start(struct ieee80211_hw *hw) if (!running) mt7915_mac_reset_counters(phy); +out: mutex_unlock(&dev->mt76.mutex); - return 0; + return ret; } static void mt7915_stop(struct ieee80211_hw *hw) @@ -631,12 +656,13 @@ static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_phy *phy = mt7915_hw_phy(hw); + int ret; mutex_lock(&dev->mt76.mutex); - mt7915_mcu_set_rts_thresh(phy, val); + ret = mt7915_mcu_set_rts_thresh(phy, val); mutex_unlock(&dev->mt76.mutex); - return 0; + return ret; } static int @@ -663,22 +689,22 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, params->buf_size); - mt7915_mcu_add_rx_ba(dev, params, true); + ret = mt7915_mcu_add_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); - mt7915_mcu_add_rx_ba(dev, params, false); + ret = mt7915_mcu_add_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - mt7915_mcu_add_tx_ba(dev, params, true); + ret = mt7915_mcu_add_tx_ba(dev, params, true); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; clear_bit(tid, &msta->ampdu_state); - mt7915_mcu_add_tx_ba(dev, params, false); + ret = mt7915_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: set_bit(tid, &msta->ampdu_state); @@ -687,7 +713,7 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; clear_bit(tid, &msta->ampdu_state); - mt7915_mcu_add_tx_ba(dev, params, false); + ret = mt7915_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } From c3800cc2919721640021c00e5845c32c2e7ad24d Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 5 Mar 2021 23:52:59 +0800 Subject: [PATCH 053/188] mt76: mt7615: check mcu returned values in mt7615_ops Properly check returned values from mcu utility routines in mt7615_ops. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 90 +++++++++++++------ 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 2380854ce386..4caf2b6b39b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -29,6 +29,7 @@ static int mt7615_start(struct ieee80211_hw *hw) struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); bool running; + int ret; if (!mt7615_wait_for_mcu_init(dev)) return -EIO; @@ -38,21 +39,38 @@ static int mt7615_start(struct ieee80211_hw *hw) running = mt7615_dev_running(dev); if (!running) { - mt7615_mcu_set_pm(dev, 0, 0); - mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); + ret = mt7615_mcu_set_pm(dev, 0, 0); + if (ret) + goto out; + + ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); + if (ret) + goto out; + mt7615_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { - mt7615_mcu_set_pm(dev, 1, 0); - mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false); + ret = mt7615_mcu_set_pm(dev, 1, 0); + if (ret) + goto out; + + ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false); + if (ret) + goto out; + mt7615_mac_enable_nf(dev, 1); } - if (mt7615_firmware_offload(dev)) - mt76_connac_mcu_set_channel_domain(phy->mt76); + if (mt7615_firmware_offload(dev)) { + ret = mt76_connac_mcu_set_channel_domain(phy->mt76); + if (ret) + goto out; + } - mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + if (ret) + goto out; set_bit(MT76_STATE_RUNNING, &phy->mt76->state); @@ -62,9 +80,10 @@ static int mt7615_start(struct ieee80211_hw *hw) if (!running) mt7615_mac_reset_counters(dev); +out: mt7615_mutex_release(dev); - return 0; + return ret; } static void mt7615_stop(struct ieee80211_hw *hw) @@ -197,7 +216,9 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); - mt7615_mcu_set_dbdc(dev); + ret = mt7615_mcu_set_dbdc(dev); + if (ret) + goto out; idx = MT7615_WTBL_RESERVED - mvif->mt76.idx; @@ -296,8 +317,13 @@ int mt7615_set_channel(struct mt7615_phy *phy) mt76_set_channel(phy->mt76); if (is_mt7615(&dev->mt76) && dev->flash_eeprom) { - mt7615_mcu_apply_rx_dcoc(phy); - mt7615_mcu_apply_tx_dpd(phy); + ret = mt7615_mcu_apply_rx_dcoc(phy); + if (ret) + goto out; + + ret = mt7615_mcu_apply_tx_dpd(phy); + if (ret) + goto out; } ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); @@ -306,8 +332,13 @@ int mt7615_set_channel(struct mt7615_phy *phy) mt7615_mac_set_timing(phy); ret = mt7615_dfs_init_radar_detector(phy); + if (ret) + goto out; + mt7615_mac_cca_stats_reset(phy); - mt7615_mcu_set_sku_en(phy, true); + ret = mt7615_mcu_set_sku_en(phy, true); + if (ret) + goto out; mt7615_mac_reset_counters(dev); phy->noise = 0; @@ -587,15 +618,21 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (err) return err; - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - mt7615_mcu_add_bss_info(phy, vif, sta, true); + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + err = mt7615_mcu_add_bss_info(phy, vif, sta, true); + if (err) + return err; + } + mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - mt7615_mcu_sta_add(&dev->phy, vif, sta, true); + err = mt7615_mcu_sta_add(&dev->phy, vif, sta, true); + if (err) + return err; mt76_connac_power_save_sched(phy->mt76, &dev->pm); - return 0; + return err; } EXPORT_SYMBOL_GPL(mt7615_mac_sta_add); @@ -715,13 +752,13 @@ static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); - int band = phy != &dev->phy; + int err, band = phy != &dev->phy; mt7615_mutex_acquire(dev); - mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band); + err = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band); mt7615_mutex_release(dev); - return 0; + return err; } static int @@ -749,16 +786,16 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, params->buf_size); - mt7615_mcu_add_rx_ba(dev, params, true); + ret = mt7615_mcu_add_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); - mt7615_mcu_add_rx_ba(dev, params, false); + ret = mt7615_mcu_add_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - mt7615_mcu_add_tx_ba(dev, params, true); + ret = mt7615_mcu_add_tx_ba(dev, params, true); ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid); ieee80211_send_bar(vif, sta->addr, tid, IEEE80211_SN_TO_SEQ(ssn)); @@ -766,7 +803,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - mt7615_mcu_add_tx_ba(dev, params, false); + ret = mt7615_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid); @@ -775,7 +812,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - mt7615_mcu_add_tx_ba(dev, params, false); + ret = mt7615_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } @@ -1091,6 +1128,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt7615_phy *phy = mt7615_hw_phy(hw); + int err; if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) return 0; @@ -1099,10 +1137,10 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, cancel_work_sync(&phy->roc_work); mt7615_mutex_acquire(phy->dev); - mt7615_mcu_set_roc(phy, vif, NULL, 0); + err = mt7615_mcu_set_roc(phy, vif, NULL, 0); mt7615_mutex_release(phy->dev); - return 0; + return err; } static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw, From 4bec61d9fb9629c21e60cd24a97235ea1f6020ec Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 4 Mar 2021 21:25:21 +0800 Subject: [PATCH 054/188] mt76: mt7663: fix when beacon filter is being applied HW beacon filter command is being applied until we're in associated state because the command would rely on the associated access point's beacon interval and DTIM information. Fixes: 7124198ab1a4 ("mt76: mt7615: enable beacon filtering by default for offload fw") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 4caf2b6b39b1..342e2c5d9766 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -238,8 +238,6 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, ret = mt7615_mcu_add_dev_info(phy, vif, true); if (ret) goto out; - - mt7615_mac_set_beacon_filter(phy, vif, true); out: mt7615_mutex_release(dev); @@ -265,7 +263,6 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - mt7615_mac_set_beacon_filter(phy, vif, false); mt7615_mcu_add_dev_info(phy, vif, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); @@ -579,6 +576,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ARP_FILTER) mt7615_mcu_update_arp_filter(hw, vif, info); + if (changed & BSS_CHANGED_ASSOC) + mt7615_mac_set_beacon_filter(phy, vif, info->assoc); + mt7615_mutex_release(dev); } From 455ae5aabcc72fed7e5c803d59d122415500dc08 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 4 Mar 2021 21:25:22 +0800 Subject: [PATCH 055/188] mt76: mt7663s: make all of packets 4-bytes aligned in sdio tx aggregation Each packet should be padded with the additional zero to become 4-bytes alignment in sdio tx aggregation. Fixes: 1522ff731f84 ("mt76: mt7663s: introduce sdio tx aggregation") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index 9fb506f2ace6..37fe65ced4fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -218,6 +218,7 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; bool mcu = q == dev->q_mcu[MT_MCUQ_WM]; struct mt76_sdio *sdio = &dev->sdio; + u8 pad; qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid; while (q->first != q->head) { @@ -234,7 +235,8 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) goto next; } - if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ) + pad = roundup(e->skb->len, 4) - e->skb->len; + if (len + e->skb->len + pad + 4 > MT76S_XMIT_BUF_SZ) break; if (mt7663s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz, @@ -252,6 +254,11 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) len += iter->len; nframes++; } + + if (unlikely(pad)) { + memset(sdio->xmit_buf[qid] + len, 0, pad); + len += pad; + } next: q->first = (q->first + 1) % q->ndesc; e->done = true; From 45247a85614b49b07b9dc59a4e6783b17e766ff2 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 4 Mar 2021 21:25:23 +0800 Subject: [PATCH 056/188] mt76: mt7663s: fix the possible device hang in high traffic Use the additional memory barrier to ensure the skb list up-to-date between the skb producer and consumer to avoid the invalid skb content written into sdio controller and then cause device hang due to mcu assert caught by WR_TIMEOUT_INT. Fixes: 1522ff731f84 ("mt76: mt7663s: introduce sdio tx aggregation") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c | 2 ++ drivers/net/wireless/mediatek/mt76/sdio.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index 37fe65ced4fd..4393dd21ebbb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -225,6 +225,8 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) struct mt76_queue_entry *e = &q->entry[q->first]; struct sk_buff *iter; + smp_rmb(); + if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) { __skb_put_zero(e->skb, 4); err = __mt7663s_xmit_queue(dev, e->skb->data, diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index 0b6facb17ff7..a18d2896ee1f 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -256,6 +256,9 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, q->entry[q->head].skb = tx_info.skb; q->entry[q->head].buf_sz = len; + + smp_wmb(); + q->head = (q->head + 1) % q->ndesc; q->queued++; From dc0a108bb060e3023090f97149e0ca81a2636e36 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 5 Mar 2021 08:22:14 +0800 Subject: [PATCH 057/188] mt76: mt7615: add missing capabilities for DBDC This improves performance for second phy. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 88a2ee7e7143..c59043195870 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -368,6 +368,11 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; else hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM; + + phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; } static void @@ -505,10 +510,6 @@ void mt7615_init_device(struct mt7615_dev *dev) mt7615_init_wiphy(hw); dev->pm.idle_timeout = MT7615_PM_TIMEOUT; - dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; mt7615_cap_dbdc_disable(dev); dev->phy.dfs_state = -1; From 782018391748f3547d44c76341ef89a2118ffe32 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 5 Mar 2021 16:46:41 +0800 Subject: [PATCH 058/188] mt76: mt7915: fix possible deadlock while mt7915_register_ext_phy() ieee80211_register_hw() is called with rtnl_lock held, and this could be caused lockdep from a work item that's on a workqueue that is flushed with the rtnl held. Move mt7915_register_ext_phy() outside the init_work(). Signed-off-by: Evelyn Tsai Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 7 ++++--- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 165be6abcc96..2ffadd22c259 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -181,8 +181,6 @@ static void mt7915_mac_init(struct mt7915_dev *dev) MT_WTBL_UPDATE_ADM_COUNT_CLEAR); for (i = 0; i < 2; i++) mt7915_mac_init_band(dev, i); - - mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b); } static int mt7915_txbf_init(struct mt7915_dev *dev) @@ -295,7 +293,6 @@ static void mt7915_init_work(struct work_struct *work) mt7915_mac_init(dev); mt7915_init_txpower(dev); mt7915_txbf_init(dev); - mt7915_register_ext_phy(dev); } static int mt7915_init_hardware(struct mt7915_dev *dev) @@ -677,6 +674,10 @@ int mt7915_register_device(struct mt7915_dev *dev) ieee80211_queue_work(mt76_hw(dev), &dev->init_work); + ret = mt7915_register_ext_phy(dev); + if (ret) + return ret; + return mt7915_init_debugfs(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 255f87aa1830..cde8c1ce3ae0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -65,6 +65,10 @@ static int mt7915_start(struct ieee80211_hw *hw) mt7915_mac_enable_nf(dev, 1); } + ret = mt7915_mcu_set_rts_thresh(phy, 0x92b); + if (ret) + goto out; + ret = mt7915_mcu_set_sku_en(phy, true); if (ret) goto out; From a2a6cd54eec4649c7cefd00ddb58f55a98c6d951 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:45 +0100 Subject: [PATCH 059/188] mt76: mt7921: reduce mcu timeouts for suspend, offload and hif_ctrl msg Reduce mcu timeout for the following uni mcu commands: - MCU_UNI_CMD_SUSPEND - MCU_UNI_CMD_OFFLOAD - MCU_UNI_CMD_HIF_CTRL This is a preliminary patch to introduce chip reset support Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index b0f8c29f756b..08da6d0f1f36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -222,8 +222,16 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, u32 val; u8 seq; - /* TODO: make dynamic based on msg type */ - mdev->mcu.timeout = 20 * HZ; + switch (cmd) { + case MCU_UNI_CMD_HIF_CTRL: + case MCU_UNI_CMD_SUSPEND: + case MCU_UNI_CMD_OFFLOAD: + mdev->mcu.timeout = HZ / 3; + break; + default: + mdev->mcu.timeout = 3 * HZ; + break; + } seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) From acf337c33de55dbeb25a8c34fa2051d42d77aecc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:46 +0100 Subject: [PATCH 060/188] mt76: introduce mcu_reset function pointer in mt76_mcu_ops structure Introduce mcu_reset function pointer in mt76_mcu_ops structure in order to run hw related reset function for the mcu running on the chipset. This is a preliminary patch to introduce chip reset for mt7921 devices. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mcu.c | 4 ++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index d3a5e2c4f12a..70624cd07449 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -99,6 +99,10 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, dev_kfree_skb(skb); } while (ret == -EAGAIN); + /* notify driver code to reset the mcu */ + if (ret == -ETIMEDOUT && dev->mcu_ops->mcu_reset) + dev->mcu_ops->mcu_reset(dev); + out: mutex_unlock(&dev->mcu.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 4d71ca228de2..4945b0430380 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -166,6 +166,7 @@ struct mt76_mcu_ops { int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *rp, int len); int (*mcu_restart)(struct mt76_dev *dev); + void (*mcu_reset)(struct mt76_dev *dev); }; struct mt76_queue_ops { From d32464e68ffc9cbec4960cd06f05bf48b3b3703f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:47 +0100 Subject: [PATCH 061/188] mt76: mt7921: introduce mt7921_run_firmware utility routine. This is a preliminary patch to introduce chip reset for mt7921 devices. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 32 +++++++++++-------- .../wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 08da6d0f1f36..6819c5dd7e94 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -927,6 +927,24 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) sizeof(data), false); } +int mt7921_run_firmware(struct mt7921_dev *dev) +{ + int err; + + err = mt7921_driver_own(dev); + if (err) + return err; + + err = mt7921_load_firmware(dev); + if (err) + return err; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt7921_mcu_fw_log_2_host(dev, 1); + + return 0; +} + int mt7921_mcu_init(struct mt7921_dev *dev) { static const struct mt76_mcu_ops mt7921_mcu_ops = { @@ -935,22 +953,10 @@ int mt7921_mcu_init(struct mt7921_dev *dev) .mcu_parse_response = mt7921_mcu_parse_response, .mcu_restart = mt7921_mcu_restart, }; - int ret; dev->mt76.mcu_ops = &mt7921_mcu_ops; - ret = mt7921_driver_own(dev); - if (ret) - return ret; - - ret = mt7921_load_firmware(dev); - if (ret) - return ret; - - set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); - mt7921_mcu_fw_log_2_host(dev, 1); - - return 0; + return mt7921_run_firmware(dev); } void mt7921_mcu_exit(struct mt7921_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 2979d06ee0ad..72dc2ba8fd40 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -220,6 +220,7 @@ void mt7921_eeprom_init_sku(struct mt7921_dev *dev); int mt7921_dma_init(struct mt7921_dev *dev); void mt7921_dma_prefetch(struct mt7921_dev *dev); void mt7921_dma_cleanup(struct mt7921_dev *dev); +int mt7921_run_firmware(struct mt7921_dev *dev); int mt7921_mcu_init(struct mt7921_dev *dev); int mt7921_mcu_add_bss_info(struct mt7921_phy *phy, struct ieee80211_vif *vif, int enable); From 1f7396acfef4691b8cf4a3e631fd3f59d779c0f2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:48 +0100 Subject: [PATCH 062/188] mt76: mt7921: introduce __mt7921_start utility routine This is a preliminary patch to introduce mt7921 chip reset support. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/main.c | 35 +++++++++++-------- .../wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 043dd77bdbe7..2b9fa4bbb21d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -169,33 +169,40 @@ void mt7921_set_stream_he_caps(struct mt7921_phy *phy) } } -static int mt7921_start(struct ieee80211_hw *hw) +int __mt7921_start(struct mt7921_phy *phy) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt76_phy *mphy = phy->mt76; int err; - mt7921_mutex_acquire(dev); - - err = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); + err = mt76_connac_mcu_set_mac_enable(mphy->dev, 0, true, false); if (err) - goto out; + return err; - err = mt76_connac_mcu_set_channel_domain(phy->mt76); + err = mt76_connac_mcu_set_channel_domain(mphy); if (err) - goto out; + return err; err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); if (err) - goto out; + return err; mt7921_mac_reset_counters(phy); - set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + set_bit(MT76_STATE_RUNNING, &mphy->state); - ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, MT7921_WATCHDOG_TIME); -out: - mt7921_mutex_release(dev); + + return 0; +} + +static int mt7921_start(struct ieee80211_hw *hw) +{ + struct mt7921_phy *phy = mt7921_hw_phy(hw); + int err; + + mt7921_mutex_acquire(phy->dev); + err = __mt7921_start(phy); + mt7921_mutex_release(phy->dev); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 72dc2ba8fd40..c1404a7f9ffb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -209,6 +209,7 @@ extern struct pci_driver mt7921_pci_driver; u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr); +int __mt7921_start(struct mt7921_phy *phy); int mt7921_register_device(struct mt7921_dev *dev); void mt7921_unregister_device(struct mt7921_dev *dev); int mt7921_eeprom_init(struct mt7921_dev *dev); From 3990465db6829c91e8ebfde51ba2d98885020249 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:49 +0100 Subject: [PATCH 063/188] mt76: dma: introduce mt76_dma_queue_reset routine Introduce mt76_dma_queue_reset utility routine to reset a given hw queue. This is a preliminary patch to introduce mt7921 chip reset support. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 46 ++++++++++++++--------- drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 6273b2cfce4f..8d4a276130cf 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -79,13 +79,38 @@ mt76_free_pending_txwi(struct mt76_dev *dev) local_bh_enable(); } +static void +mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) +{ + writel(q->desc_dma, &q->regs->desc_base); + writel(q->ndesc, &q->regs->ring_size); + q->head = readl(&q->regs->dma_idx); + q->tail = q->head; +} + +static void +mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) +{ + int i; + + if (!q) + return; + + /* clear descriptors */ + for (i = 0; i < q->ndesc; i++) + q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); + + writel(0, &q->regs->cpu_idx); + writel(0, &q->regs->dma_idx); + mt76_dma_sync_idx(dev, q); +} + static int mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, int idx, int n_desc, int bufsize, u32 ring_base) { int size; - int i; spin_lock_init(&q->lock); spin_lock_init(&q->cleanup_lock); @@ -105,14 +130,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, if (!q->entry) return -ENOMEM; - /* clear descriptors */ - for (i = 0; i < q->ndesc; i++) - q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); - - writel(q->desc_dma, &q->regs->desc_base); - writel(0, &q->regs->cpu_idx); - writel(0, &q->regs->dma_idx); - writel(q->ndesc, &q->regs->ring_size); + mt76_dma_queue_reset(dev, q); return 0; } @@ -201,15 +219,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, memset(e, 0, sizeof(*e)); } -static void -mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) -{ - writel(q->desc_dma, &q->regs->desc_base); - writel(q->ndesc, &q->regs->ring_size); - q->head = readl(&q->regs->dma_idx); - q->tail = q->head; -} - static void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) { @@ -642,6 +651,7 @@ mt76_dma_init(struct mt76_dev *dev) static const struct mt76_queue_ops mt76_dma_ops = { .init = mt76_dma_init, .alloc = mt76_dma_alloc_queue, + .reset_q = mt76_dma_queue_reset, .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw, .tx_queue_skb = mt76_dma_tx_queue_skb, .tx_cleanup = mt76_dma_tx_cleanup, diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 4945b0430380..b21a72467927 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -192,6 +192,8 @@ struct mt76_queue_ops { bool flush); void (*kick)(struct mt76_dev *dev, struct mt76_queue *q); + + void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q); }; enum mt76_wcid_flags { @@ -796,6 +798,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) +#define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__) #define mt76_for_each_q_rx(dev, i) \ for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \ From c001df978e4cb88975147ddd2c829c9e12a55076 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:50 +0100 Subject: [PATCH 064/188] mt76: dma: export mt76_dma_rx_cleanup routine Export mt76_dma_rx_cleanup routine in mt76_queue_ops data structure. This is a preliminary patch to introduce mt7921 chip reset support. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 8d4a276130cf..b87b46538b95 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -655,6 +655,7 @@ static const struct mt76_queue_ops mt76_dma_ops = { .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw, .tx_queue_skb = mt76_dma_tx_queue_skb, .tx_cleanup = mt76_dma_tx_cleanup, + .rx_cleanup = mt76_dma_rx_cleanup, .rx_reset = mt76_dma_rx_reset, .kick = mt76_dma_kick_queue, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index b21a72467927..b09b0f5ffd6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -191,6 +191,8 @@ struct mt76_queue_ops { void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q, bool flush); + void (*rx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q); + void (*kick)(struct mt76_dev *dev, struct mt76_queue *q); void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q); @@ -796,7 +798,8 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) #define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) -#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) +#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) +#define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__) From 0c1ce988460765ece1ba8eacd00533eefb6e666a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 7 Mar 2021 19:20:51 +0100 Subject: [PATCH 065/188] mt76: mt7921: add wifi reset support Introduce wifi chip reset support for mt7921 device to recover mcu hangs. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/init.c | 3 +- .../net/wireless/mediatek/mt76/mt7921/mac.c | 201 +++++++++++++----- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 3 + .../wireless/mediatek/mt76/mt7921/mt7921.h | 4 +- .../net/wireless/mediatek/mt76/mt7921/regs.h | 4 + 5 files changed, 155 insertions(+), 60 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 4070f7156aa5..262c9d150bf0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -143,7 +143,7 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); } -static void mt7921_mac_init(struct mt7921_dev *dev) +void mt7921_mac_init(struct mt7921_dev *dev) { int i; @@ -233,7 +233,6 @@ int mt7921_register_device(struct mt7921_dev *dev) INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); - init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7921_mac_reset_work); ret = mt7921_init_hardware(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 3e96bcfda45b..05971ea9f8fa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1184,43 +1184,77 @@ void mt7921_update_channel(struct mt76_dev *mdev) mt76_connac_power_save_sched(&dev->mphy, &dev->pm); } -static bool -mt7921_wait_reset_state(struct mt7921_dev *dev, u32 state) +static int +mt7921_wfsys_reset(struct mt7921_dev *dev) { - bool ret; + mt76_set(dev, 0x70002600, BIT(0)); + msleep(200); + mt76_clear(dev, 0x70002600, BIT(0)); - ret = wait_event_timeout(dev->reset_wait, - (READ_ONCE(dev->reset_state) & state), - MT7921_RESET_TIMEOUT); - - WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); - return ret; + return __mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B, + WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500); } static void -mt7921_dma_reset(struct mt7921_phy *phy) +mt7921_dma_reset(struct mt7921_dev *dev) { - struct mt7921_dev *dev = phy->dev; int i; + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST); + + /* disable WFDMA0 */ mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - usleep_range(1000, 2000); + mt76_poll(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000); - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true); + /* reset hw queues */ for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true); + mt76_queue_reset(dev, dev->mphy.q_tx[i]); - mt76_for_each_q_rx(&dev->mt76, i) { - mt76_queue_rx_reset(dev, i); - } + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_reset(dev, dev->mt76.q_mcu[i]); - /* re-init prefetch settings after reset */ + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_reset(dev, &dev->mt76.q_rx[i]); + + /* configure perfetch settings */ mt7921_dma_prefetch(dev); + /* reset dma idx */ + mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); + + /* configure delay interrupt */ + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); + + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_WB_DDONE | + MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | + MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + mt76_set(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + mt76_set(dev, 0x54000120, BIT(1)); + + /* enable interrupts for TX/RX rings */ + mt7921_irq_enable(dev, + MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); } void mt7921_tx_token_put(struct mt7921_dev *dev) @@ -1244,71 +1278,125 @@ void mt7921_tx_token_put(struct mt7921_dev *dev) idr_destroy(&dev->token); } -/* system error recovery */ -void mt7921_mac_reset_work(struct work_struct *work) +static void +mt7921_vif_connect_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) { - struct mt7921_dev *dev; + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_dev *dev = mvif->phy->dev; - dev = container_of(work, struct mt7921_dev, reset_work); + ieee80211_disconnect(vif, true); - if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA)) - return; + mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); + mt7921_mcu_set_tx(dev, vif); +} - ieee80211_stop_queues(mt76_hw(dev)); +static int +mt7921_mac_reset(struct mt7921_dev *dev) +{ + int i, err; + + mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); + + mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); - set_bit(MT76_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); - cancel_delayed_work_sync(&dev->mphy.mac_work); + skb_queue_purge(&dev->mt76.mcu.res_q); - /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); mt76_worker_disable(&dev->mt76.tx_worker); - napi_disable(&dev->mt76.napi[0]); - napi_disable(&dev->mt76.napi[1]); - napi_disable(&dev->mt76.napi[2]); + napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]); + napi_disable(&dev->mt76.napi[MT_RXQ_MCU]); + napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]); napi_disable(&dev->mt76.tx_napi); - mt7921_mutex_acquire(dev); - - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); - mt7921_tx_token_put(dev); idr_init(&dev->token); - if (mt7921_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7921_dma_reset(&dev->phy); + /* clean up hw queues */ + for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); - mt7921_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); + + mt7921_wfsys_reset(dev); + mt7921_dma_reset(dev); + + mt76_for_each_q_rx(&dev->mt76, i) { + mt76_queue_rx_reset(dev, i); + napi_enable(&dev->mt76.napi[i]); + napi_schedule(&dev->mt76.napi[i]); } - clear_bit(MT76_MCU_RESET, &dev->mphy.state); - clear_bit(MT76_RESET, &dev->mphy.state); - - mt76_worker_enable(&dev->mt76.tx_worker); napi_enable(&dev->mt76.tx_napi); napi_schedule(&dev->mt76.tx_napi); + mt76_worker_enable(&dev->mt76.tx_worker); - napi_enable(&dev->mt76.napi[0]); - napi_schedule(&dev->mt76.napi[0]); + clear_bit(MT76_MCU_RESET, &dev->mphy.state); - napi_enable(&dev->mt76.napi[1]); - napi_schedule(&dev->mt76.napi[1]); + mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + mt7921_irq_enable(dev, + MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); - napi_enable(&dev->mt76.napi[2]); - napi_schedule(&dev->mt76.napi[2]); + err = mt7921_run_firmware(dev); + if (err) + return err; - ieee80211_wake_queues(mt76_hw(dev)); + err = mt7921_mcu_set_eeprom(dev); + if (err) + return err; - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); - mt7921_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + mt7921_mac_init(dev); + return __mt7921_start(&dev->phy); +} - mt7921_mutex_release(dev); +/* system error recovery */ +void mt7921_mac_reset_work(struct work_struct *work) +{ + struct ieee80211_hw *hw; + struct mt7921_dev *dev; + int i; - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, - MT7921_WATCHDOG_TIME); + dev = container_of(work, struct mt7921_dev, reset_work); + hw = mt76_hw(dev); + + dev_err(dev->mt76.dev, "chip reset\n"); + ieee80211_stop_queues(hw); + + cancel_delayed_work_sync(&dev->mphy.mac_work); + cancel_delayed_work_sync(&dev->pm.ps_work); + cancel_work_sync(&dev->pm.wake_work); + + mutex_lock(&dev->mt76.mutex); + for (i = 0; i < 10; i++) { + if (!mt7921_mac_reset(dev)) + break; + } + mutex_unlock(&dev->mt76.mutex); + + if (i == 10) + dev_err(dev->mt76.dev, "chip reset failed\n"); + + ieee80211_wake_queues(hw); + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_vif_connect_iter, 0); +} + +void mt7921_reset(struct mt76_dev *mdev) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + + queue_work(dev->mt76.wq, &dev->reset_work); } static void @@ -1505,4 +1593,5 @@ void mt7921_coredump_work(struct work_struct *work) } dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, GFP_KERNEL); + mt7921_reset(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 6819c5dd7e94..98b48b26a6fe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -952,6 +952,7 @@ int mt7921_mcu_init(struct mt7921_dev *dev) .mcu_skb_send_msg = mt7921_mcu_send_message, .mcu_parse_response = mt7921_mcu_parse_response, .mcu_restart = mt7921_mcu_restart, + .mcu_reset = mt7921_reset, }; dev->mt76.mcu_ops = &mt7921_mcu_ops; @@ -1269,6 +1270,7 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) if (i == MT7921_DRV_OWN_RETRY_COUNT) { dev_err(dev->mt76.dev, "driver own failed\n"); + mt7921_reset(&dev->mt76); return -EIO; } @@ -1295,6 +1297,7 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev) if (i == MT7921_DRV_OWN_RETRY_COUNT) { dev_err(dev->mt76.dev, "firmware own failed\n"); + mt7921_reset(&dev->mt76); return -EIO; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index c1404a7f9ffb..df3c9730876c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -151,8 +151,6 @@ struct mt7921_dev { struct work_struct init_work; struct work_struct reset_work; - wait_queue_head_t reset_wait; - u32 reset_state; struct list_head sta_poll_list; spinlock_t sta_poll_lock; @@ -283,6 +281,7 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val) #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val) #define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0) +void mt7921_mac_init(struct mt7921_dev *dev); bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); void mt7921_mac_reset_counters(struct mt7921_phy *phy); void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, @@ -298,6 +297,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_work(struct work_struct *work); void mt7921_mac_reset_work(struct work_struct *work); +void mt7921_reset(struct mt76_dev *mdev); int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index b66e15c8ab70..035fa472fa7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -418,6 +418,10 @@ #define PCIE_LPCR_HOST_CLR_OWN BIT(1) #define PCIE_LPCR_HOST_SET_OWN BIT(0) +#define MT_WFSYS_SW_RST_B 0x18000140 +#define WFSYS_SW_RST_B BIT(0) +#define WFSYS_SW_INIT_DONE BIT(4) + #define MT_CONN_ON_MISC 0x7c0600f0 #define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) From de29d0afebad775910b428816427b55ba2bea50b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 11 Mar 2021 10:46:21 +0100 Subject: [PATCH 066/188] mt76: mt7921: remove leftovers from dbdc configuration Remove leftovers from dbdc configuration since mt7921 does not support it. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/main.c | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 2b9fa4bbb21d..1c4c26a7b5ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -459,7 +459,6 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); - bool band = phy != &dev->phy; int ret; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { @@ -480,9 +479,9 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) else phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN, + mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN, enabled); - mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); + mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter); } mt7921_mutex_release(dev); @@ -511,7 +510,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); - bool band = phy != &dev->phy; u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | MT_WF_RFCR1_DROP_BF_POLL | MT_WF_RFCR1_DROP_BA | @@ -551,12 +549,12 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); + mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter); if (*total_flags & FIF_CONTROL) - mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); + mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags); else - mt76_set(dev, MT_WF_RFCR1(band), ctl_flags); + mt76_set(dev, MT_WF_RFCR1(0), ctl_flags); mt7921_mutex_release(dev); } @@ -866,9 +864,7 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); u8 omac_idx = mvif->mt76.omac_idx; - bool band = phy != &dev->phy; union { u64 t64; u32 t32[2]; @@ -879,9 +875,9 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; /* TSF software read */ - mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE); - tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band)); - tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band)); + mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE); + tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0)); + tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0)); mt7921_mutex_release(dev); @@ -894,9 +890,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); u8 omac_idx = mvif->mt76.omac_idx; - bool band = phy != &dev->phy; union { u64 t64; u32 t32[2]; @@ -906,10 +900,10 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt7921_mutex_acquire(dev); n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; - mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]); - mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]); + mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]); + mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]); /* TSF software overwrite */ - mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_WRITE); + mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE); mt7921_mutex_release(dev); } From 1921b8925c6f2a171af6294bba6af733da2409b9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 12 Mar 2021 17:29:49 +0000 Subject: [PATCH 067/188] mt76: mt7921: remove redundant check on type Currently in the switch statement case where type is NL80211_IFTYPE_STATION there is a check to see if type is not NL80211_IFTYPE_STATION. This check is always false and is redundant dead code that can be removed. Addresses-Coverity: ("Logically dead code") Fixes: e0f9fdda81bd ("mt76: mt7921: add ieee80211_ops") Signed-off-by: Colin Ian King Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 1c4c26a7b5ce..dd22561ae800 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -240,9 +240,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) if (i) return i - 1; - if (type != NL80211_IFTYPE_STATION) - break; - /* next, try to find a free repeater entry for the sta */ i = get_free_idx(mask >> REPEATER_BSSID_START, 0, REPEATER_BSSID_MAX - REPEATER_BSSID_START); From 12f4be0e6a68650dbc9b73a047748431b2253904 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 15 Mar 2021 09:21:10 +0100 Subject: [PATCH 068/188] mt76: mt7921: remove duplicated macros in mcu.h Remove mcu definitions already available in mt76_connac_mcu.h Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mcu.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index fd67838cb565..af8b42983a00 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -177,25 +177,6 @@ enum { MCU_PHY_STATE_OFDMLQ_CNINFO, }; -#define STA_TYPE_STA BIT(0) -#define STA_TYPE_AP BIT(1) -#define STA_TYPE_ADHOC BIT(2) -#define STA_TYPE_WDS BIT(4) -#define STA_TYPE_BC BIT(5) - -#define NETWORK_INFRA BIT(16) -#define NETWORK_P2P BIT(17) -#define NETWORK_IBSS BIT(18) -#define NETWORK_WDS BIT(21) - -#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) -#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA) -#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P) -#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P) -#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS) -#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS) -#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA) - struct sec_key { u8 cipher_id; u8 cipher_len; From 1da4fd48d28436f8b690cdc2879603dede6d8355 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 22 Mar 2021 21:39:57 +0100 Subject: [PATCH 069/188] mt76: mt7915: fix key set/delete issue Deleting a key with the previous key index deletes the current key Rework the code to better keep track of multiple keys and check for the key index before deleting the current key Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/main.c | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index cde8c1ce3ae0..b32a435688bc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -346,7 +346,9 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; + u8 *wcid_keyidx = &wcid->hw_key_idx; int idx = key->keyidx; + int err = 0; /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -361,6 +363,7 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: + wcid_keyidx = &wcid->hw_key_idx2; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; case WLAN_CIPHER_SUITE_TKIP: @@ -376,16 +379,24 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + mutex_lock(&dev->mt76.mutex); + + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); - return mt7915_mcu_add_key(dev, vif, msta, key, cmd); + err = mt7915_mcu_add_key(dev, vif, msta, key, cmd); + +out: + mutex_unlock(&dev->mt76.mutex); + + return err; } static int mt7915_config(struct ieee80211_hw *hw, u32 changed) From 9add4bf2b81eb32754a6b34f7e12c0ecd2009cfc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 16 Feb 2021 15:23:13 +0100 Subject: [PATCH 070/188] mt76: mt7915: refresh repeater entry MAC address when setting BSSID When disassociating and clearing the BSSID of a repeater entry used by a client mode interface, the corresponding MAC address entry can get lost too, causing the client interface to not be able to associate anymore. Fix this by also refreshing the MAC address when setting the BSSID Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 29b5039cc286..9d0911ac1d90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1008,8 +1008,10 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct sk_buff *skb; - if (mvif->omac_idx >= REPEATER_BSSID_START) + if (mvif->omac_idx >= REPEATER_BSSID_START) { + mt7915_mcu_muar_config(phy, vif, false, enable); mt7915_mcu_muar_config(phy, vif, true, enable); + } skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL, MT7915_BSS_UPDATE_MAX_SIZE); From 14edf1093836e53804c2c6d7699b4ddcbe40c27f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Mar 2021 09:25:22 +0100 Subject: [PATCH 071/188] mt76: mt7921: get rid of mt7921_mac_wtbl_lmac_addr Get rid of mt7921_mac_wtbl_lmac_addr routine since mt7921 wtbl size is 19 entries Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 05971ea9f8fa..8faae260df79 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -51,14 +51,6 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) 0, 5000); } -static u32 mt7921_mac_wtbl_lmac_addr(struct mt7921_dev *dev, u16 wcid) -{ - mt76_wr(dev, MT_WTBLON_TOP_WDUCR, - FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); - - return MT_WTBL_LMAC_OFFS(wcid, 0); -} - static void mt7921_mac_sta_poll(struct mt7921_dev *dev) { static const u8 ac_to_tid[] = { @@ -95,7 +87,7 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) spin_unlock_bh(&dev->sta_poll_lock); idx = msta->wcid.idx; - addr = mt7921_mac_wtbl_lmac_addr(dev, idx) + 20 * 4; + addr = MT_WTBL_LMAC_OFFS(idx, 0) + 20 * 4; for (i = 0; i < IEEE80211_NUM_ACS; i++) { u32 tx_last = msta->airtime_ac[i]; From 5802106f8bc710cac0e2db6d5d2d219d5f9490b1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Mar 2021 09:37:36 +0100 Subject: [PATCH 072/188] mt76: connac: introduce mt76_sta_cmd_info data structure Introduce mt76_sta_cmd_info data structure to contain parameters passed to mt76_sta_cmd_info routine. This is preliminary patch to properly configure rcpi for mt7921 devices. Tested-by: Jayden.Kuo Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 13 ++++--- .../wireless/mediatek/mt76/mt76_connac_mcu.c | 35 ++++++++++--------- .../wireless/mediatek/mt76/mt76_connac_mcu.h | 19 +++++++--- .../net/wireless/mediatek/mt76/mt7921/main.c | 19 +++++++--- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 4ca0d8d4c536..1ed06c253816 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -988,7 +988,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable); if (enable && sta) - mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif); + mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0); wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, WTBL_RESET_AND_SET, NULL, @@ -1086,10 +1086,15 @@ __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable, int cmd) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt76_wcid *wcid; + struct mt76_sta_cmd_info info = { + .sta = sta, + .vif = vif, + .enable = enable, + .cmd = cmd, + }; - wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid; - return mt76_connac_mcu_add_sta_cmd(phy, vif, sta, wcid, enable, cmd); + info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid; + return mt76_connac_mcu_add_sta_cmd(phy, &info); } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 2cd1677d881e..bafe95210807 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -674,7 +674,8 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_sta *sta, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif, + u8 rcpi) { struct cfg80211_chan_def *chandef = &mphy->chandef; enum nl80211_band band = chandef->chan->band; @@ -723,6 +724,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, phy = (struct sta_rec_phy *)tlv; phy->phy_type = mt76_connac_get_phy_mode_v2(mphy, vif, band, sta); phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates); + phy->rcpi = rcpi; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info)); ra_info = (struct sta_rec_ra_info *)tlv; @@ -827,43 +829,42 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv); int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct mt76_wcid *wcid, - bool enable, int cmd) + struct mt76_sta_cmd_info *info) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv; struct mt76_dev *dev = phy->dev; struct wtbl_req_hdr *wtbl_hdr; struct tlv *sta_wtbl; struct sk_buff *skb; - skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid); + skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); - mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable); - if (enable && sta) - mt76_connac_mcu_sta_tlv(phy, skb, sta, vif); + mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, info->enable); + if (info->enable && info->sta) + mt76_connac_mcu_sta_tlv(phy, skb, info->sta, info->vif, + info->rcpi); sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid, WTBL_RESET_AND_SET, sta_wtbl, &skb); if (IS_ERR(wtbl_hdr)) return PTR_ERR(wtbl_hdr); - if (enable) { - mt76_connac_mcu_wtbl_generic_tlv(dev, skb, vif, sta, sta_wtbl, + if (info->enable) { + mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif, + info->sta, sta_wtbl, wtbl_hdr); - if (sta) - mt76_connac_mcu_wtbl_ht_tlv(dev, skb, sta, sta_wtbl, - wtbl_hdr); + if (info->sta) + mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta, + sta_wtbl, wtbl_hdr); } - return mt76_mcu_skb_send_msg(dev, skb, cmd, true); + return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_sta_cmd); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 950e68e11ddd..5a3efd744546 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -881,6 +881,17 @@ struct mt76_connac_suspend_tlv { u8 pad[5]; } __packed; +struct mt76_sta_cmd_info { + struct ieee80211_sta *sta; + struct mt76_wcid *wcid; + + struct ieee80211_vif *vif; + + bool enable; + int cmd; + u8 rcpi; +}; + #define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) #define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) @@ -928,7 +939,8 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, void *sta_wtbl, void *wtbl_tlv); void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_sta *sta, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif, + u8 rcpi); void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, void *sta_wtbl, void *wtbl_tlv); @@ -951,10 +963,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, struct mt76_wcid *wcid, bool enable); int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct mt76_wcid *wcid, - bool enable, int cmd); + struct mt76_sta_cmd_info *info); void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index dd22561ae800..302d8d78d6f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -624,6 +624,13 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt76_sta_cmd_info info = { + .sta = sta, + .vif = vif, + .enable = true, + .cmd = MCU_UNI_CMD_STA_REC_UPDATE, + .wcid = &msta->wcid, + }; int ret, idx; idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); @@ -650,8 +657,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7921_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - ret = mt76_connac_mcu_add_sta_cmd(&dev->mphy, vif, sta, &msta->wcid, - true, MCU_UNI_CMD_STA_REC_UPDATE); + ret = mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info); if (ret) return ret; @@ -665,12 +671,17 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt76_sta_cmd_info info = { + .sta = sta, + .vif = vif, + .cmd = MCU_UNI_CMD_STA_REC_UPDATE, + .wcid = &msta->wcid, + }; mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); mt76_connac_pm_wake(&dev->mphy, &dev->pm); - mt76_connac_mcu_add_sta_cmd(&dev->mphy, vif, sta, &msta->wcid, false, - MCU_UNI_CMD_STA_REC_UPDATE); + mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info); mt7921_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); From 93c81df520a1ba506757a47c6e4a148f4372a282 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Mar 2021 09:37:37 +0100 Subject: [PATCH 073/188] mt76: mt7921: properly configure rcpi adding a sta to the fw Properly configure rcpi based on association process rssi. rcpi is used by rate controller embedded into the fw to initialize amsdu size. Tested-by: Jayden.Kuo Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mac.c | 35 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7921/main.c | 12 +++++-- .../wireless/mediatek/mt76/mt7921/mt7921.h | 7 ++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 8faae260df79..ee6482124c0a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -9,8 +9,6 @@ #include "mac.h" #include "mcu.h" -#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) - #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) @@ -277,6 +275,37 @@ mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy, status->freq = ieee80211_channel_to_frequency(chfreq, status->band); } +static void +mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct sk_buff *skb = priv; + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (status->signal > 0) + return; + + if (!ether_addr_equal(vif->addr, hdr->addr1)) + return; + + ewma_rssi_add(&mvif->rssi, -status->signal); +} + +static void +mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (!ieee80211_is_assoc_resp(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) + return; + + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_mac_rssi_iter, skb); +} + int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -514,6 +543,8 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) mt76_insert_ccmp_hdr(skb, key_id); } + mt7921_mac_assoc_rssi(dev, skb); + if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) mt7921_mac_decode_he_radiotap(skb, status, rxv, mode); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 302d8d78d6f7..7b4f6a70f87a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -322,6 +322,8 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, mt7921_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + ewma_rssi_init(&mvif->rssi); + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; @@ -624,12 +626,14 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + int rssi = -ewma_rssi_read(&mvif->rssi); struct mt76_sta_cmd_info info = { .sta = sta, .vif = vif, .enable = true, .cmd = MCU_UNI_CMD_STA_REC_UPDATE, .wcid = &msta->wcid, + .rcpi = to_rcpi(rssi), }; int ret, idx; @@ -686,11 +690,13 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7921_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + if (vif->type == NL80211_IFTYPE_STATION) { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, - false); + ewma_rssi_init(&mvif->rssi); + if (!sta->tdls) + mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, + &mvif->sta.wcid, false); } spin_lock_bh(&dev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index df3c9730876c..5cedefc41416 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -46,6 +46,9 @@ #define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM #define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1) +#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) +#define to_rcpi(rssi) (2 * (rssi) + 220) + struct mt7921_vif; struct mt7921_sta; @@ -92,12 +95,16 @@ struct mt7921_sta { struct mt7921_sta_key_conf bip; }; +DECLARE_EWMA(rssi, 10, 8); + struct mt7921_vif { struct mt76_vif mt76; /* must be first */ struct mt7921_sta sta; struct mt7921_phy *phy; + struct ewma_rssi rssi; + struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; }; From 6104edf9e8a364c9fc586f88867850887524ca04 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 25 Mar 2021 16:06:01 +0800 Subject: [PATCH 074/188] mt76: mt7615: only enable DFS test knobs for mt7615 DFS knobs should not be visible to non-DFS devices. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/debugfs.c | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 7ae48b4fa564..1b414220521a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -517,18 +517,23 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) &fops_pm_idle_timeout); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); - debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); - /* test pattern knobs */ - debugfs_create_u8("pattern_len", 0600, dir, - &dev->radar_pattern.n_pulses); - debugfs_create_u32("pulse_period", 0600, dir, - &dev->radar_pattern.period); - debugfs_create_u16("pulse_width", 0600, dir, - &dev->radar_pattern.width); - debugfs_create_u16("pulse_power", 0600, dir, - &dev->radar_pattern.power); - debugfs_create_file("radar_trigger", 0200, dir, dev, - &fops_radar_pattern); + + if (is_mt7615(&dev->mt76)) { + debugfs_create_u32("dfs_hw_pattern", 0400, dir, + &dev->hw_pattern); + /* test pattern knobs */ + debugfs_create_u8("pattern_len", 0600, dir, + &dev->radar_pattern.n_pulses); + debugfs_create_u32("pulse_period", 0600, dir, + &dev->radar_pattern.period); + debugfs_create_u16("pulse_width", 0600, dir, + &dev->radar_pattern.width); + debugfs_create_u16("pulse_power", 0600, dir, + &dev->radar_pattern.power); + debugfs_create_file("radar_trigger", 0200, dir, dev, + &fops_radar_pattern); + } + debugfs_create_file("reset_test", 0200, dir, dev, &fops_reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir, From 69e74d7f23d515fb559b2e0bebfdf4c458d9507d Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 25 Mar 2021 16:06:02 +0800 Subject: [PATCH 075/188] mt76: mt7615: cleanup mcu tx queue in mt7615_dma_reset() With this patch, mt7615_mac_reset_work() can recover system back. Fixes: e637763b606b ("mt76: move mcu queues to mt76_dev q_mcu array") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 59aa8f84645b..17aa3e4d67ca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -2018,15 +2018,17 @@ void mt7615_dma_reset(struct mt7615_dev *dev) mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + usleep_range(1000, 2000); - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - mt76_for_each_q_rx(&dev->mt76, i) { + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) mt76_queue_rx_reset(dev, i); - } mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | From ad2a1ea49f631bb739116e9839b6f65231053112 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 25 Mar 2021 16:06:03 +0800 Subject: [PATCH 076/188] mt76: mt7622: trigger hif interrupt for system reset hif interrupt needs to be triggered after MT_MCU_INT_EVENT. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 15 ++++++++++++--- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mt7615.h | 2 ++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 17aa3e4d67ca..3d9d893dbac5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -2053,6 +2053,15 @@ void mt7615_tx_token_put(struct mt7615_dev *dev) } EXPORT_SYMBOL_GPL(mt7615_tx_token_put); +static void +mt7615_hif_int_event_trigger(struct mt7615_dev *dev, u8 event) +{ + mt76_wr(dev, MT_MCU_INT_EVENT, event); + + mt7622_trigger_hif_int(dev, true); + mt7622_trigger_hif_int(dev, false); +} + void mt7615_mac_reset_work(struct work_struct *work) { struct mt7615_phy *phy2; @@ -2095,7 +2104,7 @@ void mt7615_mac_reset_work(struct work_struct *work) mt7615_mutex_acquire(dev); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED); + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_STOPPED); mt7615_tx_token_put(dev); idr_init(&dev->token); @@ -2105,7 +2114,7 @@ void mt7615_mac_reset_work(struct work_struct *work) mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_INIT); + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_INIT); mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); } @@ -2128,7 +2137,7 @@ void mt7615_mac_reset_work(struct work_struct *work) if (ext_phy) ieee80211_wake_queues(ext_phy->hw); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE); mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); mt7615_update_beacons(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 1ed06c253816..e565fc770a0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -274,7 +274,7 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) sizeof(req), false); } -static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) +void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) { if (!is_mt7622(&dev->mt76)) return; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 84d06f2b41d4..484fc16f0c11 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -556,6 +556,8 @@ u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset); void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val); void mt7615_coredump_work(struct work_struct *work); +void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en); + /* usb */ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, From d9852ab2f362fc4fcf501f4350d007b08559ccc1 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 25 Mar 2021 16:06:04 +0800 Subject: [PATCH 077/188] mt76: mt7615: keep mcu_add_bss_info enabled till interface removal BSS_INFO_BASIC is never called alone with inactive state, which always follows beacon offload disable, so keep it enabled throughout interfaces life cycle. Inactive state also removes sta record of all connected stations, thurs causes connection lost which defeats the purpose of CSA. Lastly, this is especially an unexpected behavior that keeping mt7622 failing beacon buffer recyled when scanning channels. bss_conf change is updated with active state only, so just overwrite it. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 342e2c5d9766..e30b256784e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -253,10 +253,11 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, struct mt7615_phy *phy = mt7615_hw_phy(hw); int idx = msta->wcid.idx; - /* TODO: disable beacon for the bss */ - mt7615_mutex_acquire(dev); + mt7615_mcu_add_bss_info(phy, vif, NULL, false); + mt7615_mcu_sta_add(phy, vif, NULL, false); + mt76_testmode_reset(phy->mt76, true); if (vif == phy->monitor_vif) phy->monitor_vif = NULL; @@ -558,11 +559,11 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BEACON_ENABLED) { - mt7615_mcu_add_bss_info(phy, vif, NULL, info->enable_beacon); - mt7615_mcu_sta_add(phy, vif, NULL, info->enable_beacon); + if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { + mt7615_mcu_add_bss_info(phy, vif, NULL, true); + mt7615_mcu_sta_add(phy, vif, NULL, true); - if (vif->p2p && info->enable_beacon) + if (vif->p2p) mt7615_mcu_set_p2p_oppps(hw, vif); } From a9bae3f5361487c9b3859f288e112ad045973a4a Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 25 Mar 2021 16:06:05 +0800 Subject: [PATCH 078/188] mt76: mt7915: keep mcu_add_bss_info enabled till interface removal The same as mt7615. Keep BSS_INFO_BASIC enabled throughout interfaces life cycle. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index b32a435688bc..2fd87987312e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -256,7 +256,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, struct mt7915_phy *phy = mt7915_hw_phy(hw); int idx = msta->wcid.idx; - /* TODO: disable beacon for the bss */ + mt7915_mcu_add_bss_info(phy, vif, false); + mt7915_mcu_add_sta(dev, vif, NULL, false); mutex_lock(&dev->mt76.mutex); mt76_testmode_reset(phy->mt76, true); @@ -555,9 +556,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BEACON_ENABLED) { - mt7915_mcu_add_bss_info(phy, vif, info->enable_beacon); - mt7915_mcu_add_sta(dev, vif, NULL, info->enable_beacon); + if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { + mt7915_mcu_add_bss_info(phy, vif, true); + mt7915_mcu_add_sta(dev, vif, NULL, true); } /* ensure that enable txcmd_mode after bss_info */ From 1ebea45ef027ee31cd50ed92903071391e792edb Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 26 Mar 2021 02:28:56 +0800 Subject: [PATCH 079/188] mt76: mt7915: cleanup mcu tx queue in mt7915_dma_reset() Cleanup mcu queues in mt7915_mac_reset_work(). Fixes: e637763b606b ("mt76: move mcu queues to mt76_dev q_mcu array") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index d3a6312c058c..0924ae074db2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1515,9 +1515,8 @@ mt7915_update_beacons(struct mt7915_dev *dev) } static void -mt7915_dma_reset(struct mt7915_phy *phy) +mt7915_dma_reset(struct mt7915_dev *dev) { - struct mt7915_dev *dev = phy->dev; struct mt76_phy *mphy_ext = dev->mt76.phy2; u32 hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE; int i; @@ -1534,18 +1533,20 @@ mt7915_dma_reset(struct mt7915_phy *phy) (MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN)); } + usleep_range(1000, 2000); - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true); for (i = 0; i < __MT_TXQ_MAX; i++) { - mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); if (mphy_ext) mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true); } - mt76_for_each_q_rx(&dev->mt76, i) { + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) mt76_queue_rx_reset(dev, i); - } /* re-init prefetch settings after reset */ mt7915_dma_prefetch(dev); @@ -1630,7 +1631,7 @@ void mt7915_mac_reset_work(struct work_struct *work) idr_init(&dev->token); if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7915_dma_reset(&dev->phy); + mt7915_dma_reset(dev); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); From 1cb7ea2acb725bf8752dc765c1c1645c7ecc23bb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Mar 2021 21:52:11 +0100 Subject: [PATCH 080/188] mt76: mt7615: fix chip reset on MT7622 and MT7663e After chip reset, the DMA scheduler needs to be initialized as well. Since the code is PCI/SoC specific, move it to pci_mac.c, so that it can depend on a function in dma.c Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/dma.c | 26 +-- .../net/wireless/mediatek/mt76/mt7615/init.c | 1 - .../net/wireless/mediatek/mt76/mt7615/mac.c | 170 ------------------ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 1 + .../wireless/mediatek/mt76/mt7615/mt7615.h | 1 + .../wireless/mediatek/mt76/mt7615/pci_init.c | 1 + .../wireless/mediatek/mt76/mt7615/pci_mac.c | 168 +++++++++++++++++ 7 files changed, 187 insertions(+), 181 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 2e3120eb2da9..0ec1c526f583 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -176,6 +176,21 @@ static void mt7663_dma_sched_init(struct mt7615_dev *dev) mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987); } +void mt7615_dma_start(struct mt7615_dev *dev) +{ + /* start dma engine */ + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + + if (is_mt7622(&dev->mt76)) + mt7622_dma_sched_init(dev); + + if (is_mt7663(&dev->mt76)) + mt7663_dma_sched_init(dev); +} + int mt7615_dma_init(struct mt7615_dev *dev) { int rx_ring_size = MT7615_RX_RING_SIZE; @@ -253,20 +268,11 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000); - /* start dma engine */ - mt76_set(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_TX_DMA_EN | - MT_WPDMA_GLO_CFG_RX_DMA_EN); - /* enable interrupts for TX/RX rings */ mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | mt7615_tx_mcu_int_mask(dev) | MT_INT_MCU_CMD); - if (is_mt7622(&dev->mt76)) - mt7622_dma_sched_init(dev); - - if (is_mt7663(&dev->mt76)) - mt7663_dma_sched_init(dev); + mt7615_dma_start(dev); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index c59043195870..857fb4918975 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -504,7 +504,6 @@ void mt7615_init_device(struct mt7615_dev *dev) init_waitqueue_head(&dev->reset_wait); init_waitqueue_head(&dev->phy.roc_wait); - INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); INIT_WORK(&dev->phy.roc_work, mt7615_roc_work); timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 3d9d893dbac5..6a1395de3066 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1966,76 +1966,6 @@ void mt7615_mac_work(struct work_struct *work) MT7615_WATCHDOG_TIME); } -static bool -mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) -{ - bool ret; - - ret = wait_event_timeout(dev->reset_wait, - (READ_ONCE(dev->reset_state) & state), - MT7615_RESET_TIMEOUT); - WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); - return ret; -} - -static void -mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct ieee80211_hw *hw = priv; - struct mt7615_dev *dev = mt7615_hw_dev(hw); - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - mt7615_mcu_add_beacon(dev, hw, vif, - vif->bss_conf.enable_beacon); - break; - default: - break; - } -} - -static void -mt7615_update_beacons(struct mt7615_dev *dev) -{ - ieee80211_iterate_active_interfaces(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7615_update_vif_beacon, dev->mt76.hw); - - if (!dev->mt76.phy2) - return; - - ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7615_update_vif_beacon, dev->mt76.phy2->hw); -} - -void mt7615_dma_reset(struct mt7615_dev *dev) -{ - int i; - - mt76_clear(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | - MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); - - usleep_range(1000, 2000); - - for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - - for (i = 0; i < __MT_MCUQ_MAX; i++) - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); - - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_rx_reset(dev, i); - - mt76_set(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | - MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); -} -EXPORT_SYMBOL_GPL(mt7615_dma_reset); - void mt7615_tx_token_put(struct mt7615_dev *dev) { struct mt76_txwi_cache *txwi; @@ -2053,106 +1983,6 @@ void mt7615_tx_token_put(struct mt7615_dev *dev) } EXPORT_SYMBOL_GPL(mt7615_tx_token_put); -static void -mt7615_hif_int_event_trigger(struct mt7615_dev *dev, u8 event) -{ - mt76_wr(dev, MT_MCU_INT_EVENT, event); - - mt7622_trigger_hif_int(dev, true); - mt7622_trigger_hif_int(dev, false); -} - -void mt7615_mac_reset_work(struct work_struct *work) -{ - struct mt7615_phy *phy2; - struct mt76_phy *ext_phy; - struct mt7615_dev *dev; - - dev = container_of(work, struct mt7615_dev, reset_work); - ext_phy = dev->mt76.phy2; - phy2 = ext_phy ? ext_phy->priv : NULL; - - if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) - return; - - ieee80211_stop_queues(mt76_hw(dev)); - if (ext_phy) - ieee80211_stop_queues(ext_phy->hw); - - set_bit(MT76_RESET, &dev->mphy.state); - set_bit(MT76_MCU_RESET, &dev->mphy.state); - wake_up(&dev->mt76.mcu.wait); - cancel_delayed_work_sync(&dev->mphy.mac_work); - del_timer_sync(&dev->phy.roc_timer); - cancel_work_sync(&dev->phy.roc_work); - if (phy2) { - set_bit(MT76_RESET, &phy2->mt76->state); - cancel_delayed_work_sync(&phy2->mt76->mac_work); - del_timer_sync(&phy2->roc_timer); - cancel_work_sync(&phy2->roc_work); - } - - /* lock/unlock all queues to ensure that no tx is pending */ - mt76_txq_schedule_all(&dev->mphy); - if (ext_phy) - 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]); - napi_disable(&dev->mt76.tx_napi); - - mt7615_mutex_acquire(dev); - - mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_STOPPED); - - mt7615_tx_token_put(dev); - idr_init(&dev->token); - - if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7615_dma_reset(dev); - - mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0); - - mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_INIT); - mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); - } - - clear_bit(MT76_MCU_RESET, &dev->mphy.state); - clear_bit(MT76_RESET, &dev->mphy.state); - if (phy2) - clear_bit(MT76_RESET, &phy2->mt76->state); - - mt76_worker_enable(&dev->mt76.tx_worker); - 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]); - - ieee80211_wake_queues(mt76_hw(dev)); - if (ext_phy) - ieee80211_wake_queues(ext_phy->hw); - - mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE); - mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); - - mt7615_update_beacons(dev); - - mt7615_mutex_release(dev); - - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, - MT7615_WATCHDOG_TIME); - if (phy2) - ieee80211_queue_delayed_work(ext_phy->hw, - &phy2->mt76->mac_work, - MT7615_WATCHDOG_TIME); - -} - static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index e565fc770a0f..3855acbd4a5d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -283,6 +283,7 @@ void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) MT_INFRACFG_MISC_AP2CONN_WAKE, !en * MT_INFRACFG_MISC_AP2CONN_WAKE); } +EXPORT_SYMBOL_GPL(mt7622_trigger_hif_int); static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 484fc16f0c11..dbabdeef4e0b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -376,6 +376,7 @@ int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev, enum nl80211_band band); int mt7615_wait_pdma_busy(struct mt7615_dev *dev); int mt7615_dma_init(struct mt7615_dev *dev); +void mt7615_dma_start(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index 72395925ddee..a629d9cb3806 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -126,6 +126,7 @@ int mt7615_register_device(struct mt7615_dev *dev) int ret; mt7615_init_device(dev); + INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index 1b4cb145f38e..1b206ccdadf2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c @@ -181,3 +181,171 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } + +void mt7615_dma_reset(struct mt7615_dev *dev) +{ + int i; + + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + + usleep_range(1000, 2000); + + for (i = 0; i < __MT_TXQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); + + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_reset(dev, i); + + mt7615_dma_start(dev); +} +EXPORT_SYMBOL_GPL(mt7615_dma_reset); + +static void +mt7615_hif_int_event_trigger(struct mt7615_dev *dev, u8 event) +{ + mt76_wr(dev, MT_MCU_INT_EVENT, event); + + mt7622_trigger_hif_int(dev, true); + mt7622_trigger_hif_int(dev, false); +} + +static bool +mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) +{ + bool ret; + + ret = wait_event_timeout(dev->reset_wait, + (READ_ONCE(dev->reset_state) & state), + MT7615_RESET_TIMEOUT); + WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); + return ret; +} + +static void +mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct ieee80211_hw *hw = priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + mt7615_mcu_add_beacon(dev, hw, vif, + vif->bss_conf.enable_beacon); + break; + default: + break; + } +} + +static void +mt7615_update_beacons(struct mt7615_dev *dev) +{ + ieee80211_iterate_active_interfaces(dev->mt76.hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_update_vif_beacon, dev->mt76.hw); + + if (!dev->mt76.phy2) + return; + + ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_update_vif_beacon, dev->mt76.phy2->hw); +} + +void mt7615_mac_reset_work(struct work_struct *work) +{ + struct mt7615_phy *phy2; + struct mt76_phy *ext_phy; + struct mt7615_dev *dev; + + dev = container_of(work, struct mt7615_dev, reset_work); + ext_phy = dev->mt76.phy2; + phy2 = ext_phy ? ext_phy->priv : NULL; + + if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) + return; + + ieee80211_stop_queues(mt76_hw(dev)); + if (ext_phy) + ieee80211_stop_queues(ext_phy->hw); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mcu.wait); + cancel_delayed_work_sync(&dev->mphy.mac_work); + del_timer_sync(&dev->phy.roc_timer); + cancel_work_sync(&dev->phy.roc_work); + if (phy2) { + set_bit(MT76_RESET, &phy2->mt76->state); + cancel_delayed_work_sync(&phy2->mt76->mac_work); + del_timer_sync(&phy2->roc_timer); + cancel_work_sync(&phy2->roc_work); + } + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (ext_phy) + 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]); + napi_disable(&dev->mt76.tx_napi); + + mt7615_mutex_acquire(dev); + + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_STOPPED); + + mt7615_tx_token_put(dev); + idr_init(&dev->token); + + if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { + mt7615_dma_reset(dev); + + mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0); + + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_INIT); + mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); + } + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + clear_bit(MT76_RESET, &dev->mphy.state); + if (phy2) + clear_bit(MT76_RESET, &phy2->mt76->state); + + mt76_worker_enable(&dev->mt76.tx_worker); + 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]); + + ieee80211_wake_queues(mt76_hw(dev)); + if (ext_phy) + ieee80211_wake_queues(ext_phy->hw); + + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE); + mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + mt7615_update_beacons(dev); + + mt7615_mutex_release(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, + MT7615_WATCHDOG_TIME); + if (phy2) + ieee80211_queue_delayed_work(ext_phy->hw, + &phy2->mt76->mac_work, + MT7615_WATCHDOG_TIME); + +} From d76d6c3ba2b0addbf8398641f406b339d91b4fbc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Mar 2021 10:38:25 +0100 Subject: [PATCH 081/188] mt76: mt7615: limit firmware log message printk to buffer length Avoid including garbage from previous rx data Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 3855acbd4a5d..600c5366c099 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -424,7 +424,8 @@ mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb) break; } - wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data); + wiphy_info(mt76_hw(dev)->wiphy, "%s: %*s", type, + (int)(skb->len - sizeof(*rxd)), data); } static void From 665b2c780d63762349646e9abaea507192c6666a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Mar 2021 10:40:55 +0100 Subject: [PATCH 082/188] mt76: mt7915: limit firmware log message printk to buffer length Avoid including garbage from previous rx data Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 9d0911ac1d90..67b1426e98b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -521,7 +521,8 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb) break; } - wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data); + wiphy_info(mt76_hw(dev)->wiphy, "%s: %*s", type, + (int)(skb->len - sizeof(*rxd)), data); } static void From 7c82bbb1acc04ef38698582f6ae6c13358563406 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Mar 2021 22:49:59 +0100 Subject: [PATCH 083/188] dt-bindings:net:wireless:ieee80211: txt to yaml conversion Convert generic ieee80211 dts bindings from .txt to .yaml Signed-off-by: Lorenzo Bianconi Reviewed-by: Rob Herring Signed-off-by: Felix Fietkau --- .../bindings/net/wireless/ieee80211.txt | 24 ---------- .../bindings/net/wireless/ieee80211.yaml | 45 +++++++++++++++++++ 2 files changed, 45 insertions(+), 24 deletions(-) delete mode 100644 Documentation/devicetree/bindings/net/wireless/ieee80211.txt create mode 100644 Documentation/devicetree/bindings/net/wireless/ieee80211.yaml diff --git a/Documentation/devicetree/bindings/net/wireless/ieee80211.txt b/Documentation/devicetree/bindings/net/wireless/ieee80211.txt deleted file mode 100644 index f6442b1397f5..000000000000 --- a/Documentation/devicetree/bindings/net/wireless/ieee80211.txt +++ /dev/null @@ -1,24 +0,0 @@ -Common IEEE 802.11 properties - -This provides documentation of common properties that are valid for all wireless -devices. - -Optional properties: - - ieee80211-freq-limit : list of supported frequency ranges in KHz. This can be - used for devices that in a given config support less channels than - normally. It may happen chipset supports a wide wireless band but it is - limited to some part of it due to used antennas or power amplifier. - An example case for this can be tri-band wireless router with two - identical chipsets used for two different 5 GHz subbands. Using them - incorrectly could not work or decrease performance noticeably. - -Example: - -pcie@0,0 { - reg = <0x0000 0 0 0 0>; - wifi@0,0 { - reg = <0x0000 0 0 0 0>; - ieee80211-freq-limit = <2402000 2482000>, - <5170000 5250000>; - }; -}; diff --git a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml new file mode 100644 index 000000000000..d58e1571df9b --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/wireless/ieee80211.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Common IEEE 802.11 Binding + +maintainers: + - Lorenzo Bianconi + +description: | + This provides documentation of common properties that are valid for + all wireless devices + +properties: + ieee80211-freq-limit: + $ref: /schemas/types.yaml#/definitions/uint32-matrix + items: + minItems: 2 + maxItems: 2 + description: + List of supported frequency ranges in KHz. This can be used for devices + that in a given config support less channels than normally. It may happen + chipset supports a wide wireless band but it is limited to some part of + it due to used antennas or power amplifier. An example case for this + can be tri-band wireless router with two identical chipsets used for two + different 5 GHz subbands. Using them incorrectly could not work or + decrease performance noticeably + +additionalProperties: true + +examples: + - | + pcie0 { + #address-cells = <3>; + #size-cells = <2>; + wifi@0,0 { + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <2402000 2482000>, + <5170000 5250000>; + }; + }; From 1735e44dddc04e27860b6fc5099a64e4866115b7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 28 Mar 2021 19:37:48 +0200 Subject: [PATCH 084/188] dt-bindings:net:wireless:mediatek,mt76: txt to yaml conversion Convert mt76 dts bindings from .txt to .yaml Signed-off-by: Lorenzo Bianconi Reviewed-by: Rob Herring Signed-off-by: Felix Fietkau --- .../bindings/net/wireless/mediatek,mt76.txt | 78 ----------- .../bindings/net/wireless/mediatek,mt76.yaml | 121 ++++++++++++++++++ 2 files changed, 121 insertions(+), 78 deletions(-) delete mode 100644 Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt create mode 100644 Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt deleted file mode 100644 index ab7e7a00e534..000000000000 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt +++ /dev/null @@ -1,78 +0,0 @@ -* MediaTek mt76xx devices - -This node provides properties for configuring the MediaTek mt76xx wireless -device. The node is expected to be specified as a child node of the PCI -controller to which the wireless chip is connected. - -Alternatively, it can specify the wireless part of the MT7628/MT7688 or -MT7622 SoC. For SoC, use the following compatible strings: - -compatible: -- "mediatek,mt7628-wmac" for MT7628/MT7688 -- "mediatek,mt7622-wmac" for MT7622 - -properties: -- reg: Address and length of the register set for the device. -- interrupts: Main device interrupt - -MT7622 specific properties: -- power-domains: phandle to the power domain that the WMAC is part of -- mediatek,infracfg: phandle to the infrastructure bus fabric syscon node - -Optional properties: - -- ieee80211-freq-limit: See ieee80211.txt -- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data -- big-endian: if the radio eeprom partition is written in big-endian, specify - this property -- mediatek,eeprom-merge-otp: Merge EEPROM data with OTP data. Can be used on - boards where the flash calibration data is generic and specific calibration - data should be pulled from the OTP ROM - -The MAC address can as well be set with corresponding optional properties -defined in net/ethernet.txt. - -Optional nodes: -- led: Properties for a connected LED - Optional properties: - - led-sources: See Documentation/devicetree/bindings/leds/common.txt - -&pcie { - pcie0 { - wifi@0,0 { - compatible = "mediatek,mt76"; - reg = <0x0000 0 0 0 0>; - ieee80211-freq-limit = <5000000 6000000>; - mediatek,mtd-eeprom = <&factory 0x8000>; - big-endian; - - led { - led-sources = <2>; - }; - }; - }; -}; - -MT7628 example: - -wmac: wmac@10300000 { - compatible = "mediatek,mt7628-wmac"; - reg = <0x10300000 0x100000>; - - interrupt-parent = <&cpuintc>; - interrupts = <6>; - - mediatek,mtd-eeprom = <&factory 0x0000>; -}; - -MT7622 example: - -wmac: wmac@18000000 { - compatible = "mediatek,mt7622-wmac"; - reg = <0 0x18000000 0 0x100000>; - interrupts = ; - - mediatek,infracfg = <&infracfg>; - - power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>; -}; diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml new file mode 100644 index 000000000000..d6f835d17d66 --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/wireless/mediatek,mt76.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek mt76 wireless devices Generic Binding + +maintainers: + - Felix Fietkau + - Lorenzo Bianconi + - Ryder Lee + +description: | + This node provides properties for configuring the MediaTek mt76xx + wireless device. The node is expected to be specified as a child + node of the PCI controller to which the wireless chip is connected. + Alternatively, it can specify the wireless part of the MT7628/MT7688 + or MT7622 SoC. + +allOf: + - $ref: ieee80211.yaml# + +properties: + compatible: + enum: + - mediatek,mt76 + - mediatek,mt7628-wmac + - mediatek,mt7622-wmac + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + power-domains: + maxItems: 1 + + mediatek,infracfg: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the infrastructure bus fabric syscon node. + This property is MT7622 specific + + ieee80211-freq-limit: true + + mediatek,mtd-eeprom: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Phandle to a MTD partition + offset containing EEPROM data + + big-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: + Specify if the radio eeprom partition is written in big-endian + + mediatek,eeprom-merge-otp: + type: boolean + description: + Merge EEPROM data with OTP data. Can be used on boards where the flash + calibration data is generic and specific calibration data should be + pulled from the OTP ROM + + led: + type: object + $ref: /schemas/leds/common.yaml# + additionalProperties: false + properties: + led-sources: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pcie0 { + #address-cells = <3>; + #size-cells = <2>; + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + mediatek,mtd-eeprom = <&factory 0x8000>; + big-endian; + + led { + led-sources = <2>; + }; + }; + }; + + - | + wifi@10300000 { + compatible = "mediatek,mt7628-wmac"; + reg = <0x10300000 0x100000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + mediatek,mtd-eeprom = <&factory 0x0>; + }; + + - | + #include + #include + wifi@18000000 { + compatible = "mediatek,mt7622-wmac"; + reg = <0x10300000 0x100000>; + interrupts = ; + + mediatek,infracfg = <&infracfg>; + + power-domains = <&scpsys 3>; + }; From 2df51a2b7a256b242a91450325c143faae13f234 Mon Sep 17 00:00:00 2001 From: Guobin Huang Date: Sat, 27 Mar 2021 17:56:18 +0800 Subject: [PATCH 085/188] mt76: mt7615: remove redundant dev_err call in mt7622_wmac_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Reported-by: Hulk Robot Signed-off-by: Guobin Huang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/soc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c index 9aa5183c7a56..be9a69fe1b38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -40,10 +40,8 @@ static int mt7622_wmac_probe(struct platform_device *pdev) return irq; mem_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mem_base)) { - dev_err(&pdev->dev, "Failed to get memory resource\n"); + if (IS_ERR(mem_base)) return PTR_ERR(mem_base); - } return mt7615_mmio_probe(&pdev->dev, mem_base, irq, mt7615e_reg_map); } From a226ccd04c479ccd23d6927c64bad1b441707f70 Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Thu, 1 Apr 2021 10:31:29 +0800 Subject: [PATCH 086/188] mt76: mt7915: fix txpower init for TSSI off chips Fix incorrect txpower init value for TSSI off chips which causes too small txpower. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7915/eeprom.c | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 660398ac53c2..738ecf8f4fa2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -124,7 +124,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, struct ieee80211_channel *chan, u8 chain_idx) { - int index; + int index, target_power; bool tssi_on; if (chain_idx > 3) @@ -133,15 +133,22 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, tssi_on = mt7915_tssi_enabled(dev, chan->band); if (chan->band == NL80211_BAND_2GHZ) { - index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on; - } else { - int group = tssi_on ? - mt7915_get_channel_group(chan->hw_value) : 8; + index = MT_EE_TX0_POWER_2G + chain_idx * 3; + target_power = mt7915_eeprom_read(dev, index); - index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group; + if (!tssi_on) + target_power += mt7915_eeprom_read(dev, index + 1); + } else { + int group = mt7915_get_channel_group(chan->hw_value); + + index = MT_EE_TX0_POWER_5G + chain_idx * 12; + target_power = mt7915_eeprom_read(dev, index + group); + + if (!tssi_on) + target_power += mt7915_eeprom_read(dev, index + 8); } - return mt7915_eeprom_read(dev, index); + return target_power; } static const u8 sku_cck_delta_map[] = { From 60468f7fd7072c804b2613f1cadabace8d77d311 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 27 Mar 2021 10:10:14 +0100 Subject: [PATCH 087/188] mt76: mt7921: fix key set/delete issue Similar to the mt7915 driver, deleting a key with the previous key index deletes the current key. Rework the code to better keep track of multiple keys and check for the key index before deleting the current key Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/main.c | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 7b4f6a70f87a..0be00389c7ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -412,7 +412,8 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; - int idx = key->keyidx; + u8 *wcid_keyidx = &wcid->hw_key_idx; + int idx = key->keyidx, err = 0; /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -428,6 +429,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + wcid_keyidx = &wcid->hw_key_idx2; break; case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: @@ -442,16 +444,23 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + mt7921_mutex_acquire(dev); + + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); - return mt7921_mcu_add_key(dev, vif, msta, key, cmd); + err = mt7921_mcu_add_key(dev, vif, msta, key, cmd); +out: + mt7921_mutex_release(dev); + + return err; } static int mt7921_config(struct ieee80211_hw *hw, u32 changed) From 859c85fd19715349ce01539459095fd5fc7e483a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 3 Apr 2021 14:26:39 +0200 Subject: [PATCH 088/188] mt76: mt7921: always wake the device in mt7921_remove_interface Make sure the mcu is not in sleep mode before sending mcu messages in mt7921_remove_interface routine. Fixes: 1d8efc741df80 ("mt76: mt7921: introduce Runtime PM support") Co-developed-by: Sean Wang Signed-off-by: Sean Wang Co-developed-by: Leon Yen Signed-off-by: Leon Yen Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 0be00389c7ed..06a47cab494e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -354,12 +354,12 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, if (vif == phy->monitor_vif) phy->monitor_vif = NULL; + mt7921_mutex_acquire(dev); mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - mt7921_mutex_acquire(dev); dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mt7921_mutex_release(dev); From c7cc5ec5730321ea6c86f0f87cb562fc3827b0d3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 3 Apr 2021 14:35:12 +0200 Subject: [PATCH 089/188] mt76: mt7921: rework mt7921_mcu_debug_msg_event routine Rework mt7921_mcu_debug_msg_event routing removing unnecessary assignments and relying on wiphy_info Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 98b48b26a6fe..9283f9865ad5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -474,29 +474,27 @@ mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb) static void mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) { - struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data; - struct debug_msg { + struct mt7921_debug_msg { __le16 id; u8 type; u8 flag; __le32 value; __le16 len; u8 content[512]; - } __packed * debug_msg; - u16 cur_len; - int i; + } __packed * msg; - skb_pull(skb, sizeof(*rxd)); - debug_msg = (struct debug_msg *)skb->data; + skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + msg = (struct mt7921_debug_msg *)skb->data; - cur_len = min_t(u16, le16_to_cpu(debug_msg->len), 512); + if (msg->type == 3) { /* fw log */ + u16 len = min_t(u16, le16_to_cpu(msg->len), 512); + int i; - if (debug_msg->type == 0x3) { - for (i = 0 ; i < cur_len; i++) - if (!debug_msg->content[i]) - debug_msg->content[i] = ' '; - - dev_dbg(dev->mt76.dev, "%s", debug_msg->content); + for (i = 0 ; i < len; i++) { + if (!msg->content[i]) + msg->content[i] = ' '; + } + wiphy_info(mt76_hw(dev)->wiphy, "%*s", len, msg->content); } } From 8a5a5dbfc18c667832e1f73b436dc324659fbbf8 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sun, 4 Apr 2021 15:48:23 +0800 Subject: [PATCH 090/188] mt76: mt7615: fix .add_beacon_offload() ieee80211_beacon_get_template() returns NULL when beacon state is disabled, so beacon_offload cannot be disabled for some devices. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 600c5366c099..6ca9e9840399 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -702,6 +702,9 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, }; struct sk_buff *skb; + if (!enable) + goto out; + skb = ieee80211_beacon_get_template(hw, vif, &offs); if (!skb) return -EINVAL; @@ -731,6 +734,7 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, } dev_kfree_skb(skb); +out: return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req, sizeof(req), true); } @@ -1164,8 +1168,8 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, __le16 tim_ie_pos; __le16 csa_ie_pos; __le16 bcc_ie_pos; - /* 0: enable beacon offload - * 1: disable beacon offload + /* 0: disable beacon offload + * 1: enable beacon offload * 2: update probe respond offload */ u8 enable; @@ -1188,6 +1192,9 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, }; struct sk_buff *skb; + if (!enable) + goto out; + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); if (!skb) return -EINVAL; @@ -1212,6 +1219,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, } dev_kfree_skb(skb); +out: return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, &req, sizeof(req), true); } From ac15f9b6da3957b360c356a3a6bb74f5727e433e Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sun, 4 Apr 2021 15:48:24 +0800 Subject: [PATCH 091/188] mt76: mt7915: fix mt7915_mcu_add_beacon ieee80211_beacon_get_template() returns NULL when beacon state is disabled. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 67b1426e98b6..3507fd135dfe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2451,6 +2451,17 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct bss_info_bcn *bcn; int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE; + rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); + if (IS_ERR(rskb)) + return PTR_ERR(rskb); + + tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); + bcn = (struct bss_info_bcn *)tlv; + bcn->enable = en; + + if (!en) + goto out; + skb = ieee80211_beacon_get_template(hw, vif, &offs); if (!skb) return -EINVAL; @@ -2461,16 +2472,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, return -EINVAL; } - rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); - if (IS_ERR(rskb)) { - dev_kfree_skb(skb); - return PTR_ERR(rskb); - } - - tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); - bcn = (struct bss_info_bcn *)tlv; - bcn->enable = en; - if (mvif->band_idx) { info = IEEE80211_SKB_CB(skb); info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; @@ -2481,6 +2482,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, mt7915_mcu_beacon_cont(dev, rskb, skb, bcn, &offs); dev_kfree_skb(skb); +out: return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, MCU_EXT_CMD(BSS_INFO_UPDATE), true); } From e07419a7dca97dd9bddfe5d099380857c19535f3 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 6 Apr 2021 12:46:09 +0800 Subject: [PATCH 092/188] mt76: mt7915: add wifi subsystem reset Reset wifi subsystem when MCU is already running. Fixes firmware download failure after soft reboot on systems where the PCIe reset could not be performed properly. Signed-off-by: Ryder Lee Co-developed-by: Felix Fietkau Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/init.c | 58 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 15 +---- .../net/wireless/mediatek/mt76/mt7915/regs.h | 13 +++++ 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 2ffadd22c259..261f5ab23721 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -4,6 +4,7 @@ #include #include "mt7915.h" #include "mac.h" +#include "mcu.h" #include "eeprom.h" #define CCK_RATE(_idx, _rate) { \ @@ -295,9 +296,50 @@ static void mt7915_init_work(struct work_struct *work) mt7915_txbf_init(dev); } +static void mt7915_wfsys_reset(struct mt7915_dev *dev) +{ + u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; + u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); + +#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) +#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) + + mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM); + + /* change to software control */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* reset wfsys */ + val &= ~MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* release wfsys then mcu re-excutes romcode */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* switch to hw control */ + val &= ~MT_TOP_PWR_SW_RST; + val |= MT_TOP_PWR_HW_CTRL; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* check whether mcu resets to default */ + if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT, + MT_MCU_DUMMY_DEFAULT, 1000)) { + dev_err(dev->mt76.dev, "wifi subsystem reset failure\n"); + return; + } + + /* wfsys reset won't clear host registers */ + mt76_clear(dev, reg, MT_TOP_MISC_FW_STATE); + + msleep(100); +} + static int mt7915_init_hardware(struct mt7915_dev *dev) { int ret, idx; + u32 val; mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); @@ -307,6 +349,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); + val = mt76_rr(dev, mt7915_reg_map_l1(dev, MT_TOP_MISC)); + + /* If MCU was already running, it is likely in a bad state */ + if (FIELD_GET(MT_TOP_MISC_FW_STATE, val) > FW_STATE_FW_DOWNLOAD) + mt7915_wfsys_reset(dev); + ret = mt7915_dma_init(dev); if (ret) return ret; @@ -320,8 +368,14 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); ret = mt7915_mcu_init(dev); - if (ret) - return ret; + if (ret) { + /* Reset and try again */ + mt7915_wfsys_reset(dev); + + ret = mt7915_mcu_init(dev); + if (ret) + return ret; + } ret = mt7915_eeprom_init(dev); if (ret < 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 3507fd135dfe..639f65d63add 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2784,21 +2784,8 @@ out: static int mt7915_load_firmware(struct mt7915_dev *dev) { + u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); int ret; - u32 val, reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); - - val = FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD); - - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, val, 1000)) { - /* restart firmware once */ - __mt76_mcu_restart(&dev->mt76); - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, - val, 1000)) { - dev_err(dev->mt76.dev, - "Firmware is not ready for download\n"); - return -EIO; - } - } ret = mt7915_load_patch(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index ed0c9a24bb53..dfb8880657bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -4,6 +4,11 @@ #ifndef __MT7915_REGS_H #define __MT7915_REGS_H +/* MCU WFDMA0 */ +#define MT_MCU_WFDMA0_BASE 0x2000 +#define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs)) +#define MT_MCU_WFDMA0_DUMMY_CR MT_MCU_WFDMA0(0x120) + /* MCU WFDMA1 */ #define MT_MCU_WFDMA1_BASE 0x3000 #define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) @@ -396,6 +401,14 @@ #define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) #define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2) +#define MT_TOP_RGU_BASE 0xf0000 +#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0)) +#define MT_TOP_PWR_KEY (0x5746 << 16) +#define MT_TOP_PWR_SW_RST BIT(0) +#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2) +#define MT_TOP_PWR_HW_CTRL BIT(4) +#define MT_TOP_PWR_PWR_ON BIT(7) + #define MT_INFRA_CFG_BASE 0xf1000 #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) From f2d167c7dd2c0bc444e2d5639bcf856d0ea09a71 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 4 Apr 2021 13:36:57 +0200 Subject: [PATCH 093/188] mt76: mt7921: introduce MT_WFDMA_DUMMY_CR definition Introduce MT_WFDMA_DUMMY_CR definition and remove magic numbers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 60de29a921a8..992faf82ad09 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -323,7 +323,7 @@ int mt7921_dma_init(struct mt7921_dev *dev) mt76_set(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_set(dev, 0x54000120, BIT(1)); + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); /* enable interrupts for TX/RX rings */ mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index ee6482124c0a..f3a537c6e3c8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1272,7 +1272,7 @@ mt7921_dma_reset(struct mt7921_dev *dev) mt76_set(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_set(dev, 0x54000120, BIT(1)); + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); /* enable interrupts for TX/RX rings */ mt7921_irq_enable(dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 035fa472fa7d..5b1bb5f85e5d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -385,6 +385,12 @@ #define MT_TOP_MISC MT_TOP(0xf0) #define MT_TOP_MISC_FW_STATE GENMASK(2, 0) +#define MT_MCU_WPDMA0_BASE 0x54000000 +#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs)) + +#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) +#define MT_WFDMA_NEED_REINIT BIT(1) + #define MT_HW_BOUND 0x70010020 #define MT_HW_CHIPID 0x70010200 #define MT_HW_REV 0x70010204 From 9c9d83213424679b087267600d53a35acfa0201f Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 6 Apr 2021 11:34:34 +0800 Subject: [PATCH 094/188] mt76: mt7921: fix inappropriate WoW setup with the missing ARP informaiton Fix the Wake-on-WoWLAN failure should rely on ARP Information is being updated in time to the firmware. Fixes: ffa1bf97425b ("mt76: mt7921: introduce PM support") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/main.c | 3 ++ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 44 +++++++++++++++++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 3 ++ 3 files changed, 50 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 06a47cab494e..32b1cd0bca1f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -626,6 +626,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) mt7921_bss_bcnft_apply(dev, vif, info->assoc); + if (changed & BSS_CHANGED_ARP_FILTER) + mt7921_mcu_update_arp_filter(hw, vif, info); + mt7921_mutex_release(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 9283f9865ad5..353877f1c762 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1325,3 +1325,47 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); } } + +int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct sk_buff *skb; + int i, len = min_t(int, info->arp_addr_cnt, + IEEE80211_BSS_ARP_ADDR_LIST_LEN); + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_arpns_tlv arp; + } req_hdr = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arp = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP), + .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)), + .ips_num = len, + .mode = 2, /* update */ + .option = 1, + }, + }; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, + sizeof(req_hdr) + len * sizeof(__be32)); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &req_hdr, sizeof(req_hdr)); + for (i = 0; i < len; i++) { + u8 *addr = (u8 *)skb_put(skb, sizeof(__be32)); + + memcpy(addr, &info->arp_addr_list[i], sizeof(__be32)); + } + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, + true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 5cedefc41416..ebe51017dd55 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -348,4 +348,7 @@ int mt7921_mac_set_beacon_filter(struct mt7921_phy *phy, bool enable); void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); void mt7921_coredump_work(struct work_struct *work); +int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info); #endif From 9db419f0cb39a63fb2f645a846cae17b81cd5c96 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 6 Apr 2021 11:34:35 +0800 Subject: [PATCH 095/188] mt76: mt7921: fix the dwell time control dwell time for the scan is not configurable according to the current firmware submitted into linux-firmware.git, so leave the dwell time 0 to indicate the dwell time always determined by the firmware. Fixes: 399090ef9605 ("mt76: mt76_connac: move hw_scan and sched_scan routine in mt76_connac_mcu module") Suggested-by: Soul Huang Co-developed-by: YN Chen Signed-off-by: YN Chen Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index bafe95210807..1bd6294042b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1332,7 +1332,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, { struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct cfg80211_scan_request *sreq = &scan_req->req; - int n_ssids = 0, err, i, duration = MT76_CONNAC_SCAN_CHANNEL_TIME; + int n_ssids = 0, err, i, duration; int ext_channels_num = max_t(int, sreq->n_channels - 32, 0); struct ieee80211_channel **scan_list = sreq->channels; struct mt76_dev *mdev = phy->dev; @@ -1369,6 +1369,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, req->ssid_type_ext = n_ssids ? BIT(0) : 0; req->ssids_num = n_ssids; + duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME; /* increase channel time for passive scan */ if (!sreq->n_ssids) duration *= 2; From e230f0c44f011f3270680a506b19b7e84c5e8923 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 6 Apr 2021 11:34:36 +0800 Subject: [PATCH 096/188] mt76: mt7921: fix kernel crash when the firmware fails to download Fix kernel crash when the firmware is missing or fails to download. [ 9.444758] kernel BUG at drivers/pci/msi.c:375! [ 9.449363] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [ 9.501033] pstate: a0400009 (NzCv daif +PAN -UAO) [ 9.505814] pc : free_msi_irqs+0x180/0x184 [ 9.509897] lr : free_msi_irqs+0x40/0x184 [ 9.513893] sp : ffffffc015193870 [ 9.517194] x29: ffffffc015193870 x28: 00000000f0e94fa2 [ 9.522492] x27: 0000000000000acd x26: 000000000000009a [ 9.527790] x25: ffffffc0152cee58 x24: ffffffdbb383e0d8 [ 9.533087] x23: ffffffdbb38628d0 x22: 0000000000040200 [ 9.538384] x21: ffffff8cf7de7318 x20: ffffff8cd65a2480 [ 9.543681] x19: ffffff8cf7de7000 x18: 0000000000000000 [ 9.548979] x17: ffffff8cf9ca03b4 x16: ffffffdc13ad9a34 [ 9.554277] x15: 0000000000000000 x14: 0000000000080800 [ 9.559575] x13: ffffff8cd65a2980 x12: 0000000000000000 [ 9.564873] x11: ffffff8cfa45d820 x10: ffffff8cfa45d6d0 [ 9.570171] x9 : 0000000000000040 x8 : ffffff8ccef1b780 [ 9.575469] x7 : aaaaaaaaaaaaaaaa x6 : 0000000000000000 [ 9.580766] x5 : ffffffdc13824900 x4 : ffffff8ccefe0000 [ 9.586063] x3 : 0000000000000000 x2 : 0000000000000000 [ 9.591362] x1 : 0000000000000125 x0 : ffffff8ccefe0000 [ 9.596660] Call trace: [ 9.599095] free_msi_irqs+0x180/0x184 [ 9.602831] pci_disable_msi+0x100/0x130 [ 9.606740] pci_free_irq_vectors+0x24/0x30 [ 9.610915] mt7921_pci_probe+0xbc/0x250 [mt7921e] [ 9.615693] pci_device_probe+0xd4/0x14c [ 9.619604] really_probe+0x134/0x2ec [ 9.623252] driver_probe_device+0x64/0xfc [ 9.627335] device_driver_attach+0x4c/0x6c [ 9.631506] __driver_attach+0xac/0xc0 [ 9.635243] bus_for_each_dev+0x8c/0xd4 [ 9.639066] driver_attach+0x2c/0x38 [ 9.642628] bus_add_driver+0xfc/0x1d0 [ 9.646365] driver_register+0x64/0xf8 [ 9.650101] __pci_register_driver+0x6c/0x7c [ 9.654360] init_module+0x28/0xfdc [mt7921e] [ 9.658704] do_one_initcall+0x13c/0x2d0 [ 9.662615] do_init_module+0x58/0x1e8 [ 9.666351] load_module+0xd80/0xeb4 [ 9.669912] __arm64_sys_finit_module+0xa8/0xe0 [ 9.674430] el0_svc_common+0xa4/0x16c [ 9.678168] el0_svc_compat_handler+0x2c/0x40 [ 9.682511] el0_svc_compat+0x8/0x10 [ 9.686076] Code: a94257f6 f9400bf7 a8c47bfd d65f03c0 (d4210000) [ 9.692155] ---[ end trace 7621f966afbf0a29 ]--- [ 9.697385] Kernel panic - not syncing: Fatal exception [ 9.702599] SMP: stopping secondary CPUs [ 9.706549] Kernel Offset: 0x1c03600000 from 0xffffffc010000000 [ 9.712456] PHYS_OFFSET: 0xfffffff440000000 [ 9.716625] CPU features: 0x080026,2a80aa18 [ 9.720795] Memory Limit: none Fixes: 5c14a5f944b9 ("mt76: mt7921: introduce mt7921e support") Reported-by: Claire Chang Co-developed-by: YN Chen Signed-off-by: YN Chen Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index e94523bf19be..40e2086d075c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -146,10 +146,12 @@ static int mt7921_pci_probe(struct pci_dev *pdev, ret = mt7921_register_device(dev); if (ret) - goto err_free_dev; + goto err_free_irq; return 0; +err_free_irq: + devm_free_irq(&pdev->dev, pdev->irq, dev); err_free_dev: mt76_free_device(&dev->mt76); err_free_pci_vec: From 49897c529f85504139a6e54417a65f26a07492d2 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 6 Apr 2021 11:34:37 +0800 Subject: [PATCH 097/188] mt76: mt7921: fix the insmod hangs Fix the second insert module causing the device hangs after remove module. Fixes: 1c099ab44727 ("mt76: mt7921: add MCU support") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 -- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 13 +------------ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 262c9d150bf0..9046bbfc0690 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -273,8 +273,6 @@ void mt7921_unregister_device(struct mt7921_dev *dev) { mt76_unregister_device(&dev->mt76); mt7921_mcu_exit(dev); - mt7921_dma_cleanup(dev); - mt7921_tx_token_put(dev); tasklet_disable(&dev->irq_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index f3a537c6e3c8..36eaa9d97f64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1207,8 +1207,7 @@ void mt7921_update_channel(struct mt76_dev *mdev) mt76_connac_power_save_sched(&dev->mphy, &dev->pm); } -static int -mt7921_wfsys_reset(struct mt7921_dev *dev) +int mt7921_wfsys_reset(struct mt7921_dev *dev) { mt76_set(dev, 0x70002600, BIT(0)); msleep(200); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 353877f1c762..b233b12860ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -960,18 +960,7 @@ int mt7921_mcu_init(struct mt7921_dev *dev) void mt7921_mcu_exit(struct mt7921_dev *dev) { - u32 reg = mt7921_reg_map_l1(dev, MT_TOP_MISC); - - __mt76_mcu_restart(&dev->mt76); - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, - FIELD_PREP(MT_TOP_MISC_FW_STATE, - FW_STATE_FW_DOWNLOAD), 1000)) { - dev_err(dev->mt76.dev, "Failed to exit mcu\n"); - return; - } - - reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); - mt76_wr(dev, reg, MT_TOP_LPCR_HOST_FW_OWN); + mt7921_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index ebe51017dd55..e4211b049040 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -351,4 +351,5 @@ void mt7921_coredump_work(struct work_struct *work); int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info); +int mt7921_wfsys_reset(struct mt7921_dev *dev); #endif From 4da64fe086d95daa66d0def40fbd1b02d4f813fd Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 6 Apr 2021 11:34:39 +0800 Subject: [PATCH 098/188] mt76: mt7921: reduce the data latency during hw scan Reduce the data latency during hw_scan by the split scan which would switch back to operational channel right after scanning each channel done. Suggested-by: Asda Wen Suggested-by: Soul Huang Co-developed-by: YN Chen Signed-off-by: YN Chen Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 5 ++++- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 1bd6294042b6..4892728ad9bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1395,11 +1395,14 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, req->ies_len = cpu_to_le16(sreq->ie_len); } + if (is_mt7921(phy->dev)) + req->scan_func |= SCAN_FUNC_SPLIT_SCAN; + memcpy(req->bssid, sreq->bssid, ETH_ALEN); if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { get_random_mask_addr(req->random_mac, sreq->mac_addr, sreq->mac_addr_mask); - req->scan_func = 1; + req->scan_func |= SCAN_FUNC_RANDOM_MAC; } err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CMD_START_HW_SCAN, false); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 5a3efd744546..6f9b7807305a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -362,6 +362,9 @@ enum { #define NETWORK_IBSS BIT(18) #define NETWORK_WDS BIT(21) +#define SCAN_FUNC_RANDOM_MAC BIT(0) +#define SCAN_FUNC_SPLIT_SCAN BIT(5) + #define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) #define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA) #define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P) From b4403cee6400c5f679e9c4a82b91d61aa961eccf Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 23 Mar 2021 22:47:37 +0100 Subject: [PATCH 099/188] mt76: fix potential DMA mapping leak With buf uninitialized in mt76_dma_tx_queue_skb_raw, its field skip_unmap could potentially inherit a non-zero value from stack garbage. If this happens, it will cause DMA mappings for MCU command frames to not be unmapped after completion Fixes: 27d5c528a7ca ("mt76: fix double DMA unmap of the first buffer on 7615/7915") Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index b87b46538b95..6ea58aecca41 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -318,7 +318,7 @@ static int mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, u32 tx_info) { - struct mt76_queue_buf buf; + struct mt76_queue_buf buf = {}; dma_addr_t addr; if (q->queued + 1 >= q->ndesc - 1) From 92e916362ba58e080a8b8e97556d11670ea6ce3d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 Apr 2021 12:46:17 +0200 Subject: [PATCH 100/188] mt76: mt7921: remove 80+80 MHz support capabilities This mode is not supported by the hardware Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 3 --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 9046bbfc0690..b34db6e8d0ae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -250,9 +250,6 @@ int mt7921_register_device(struct mt7921_dev *dev) dev->mphy.sband_5g.sband.vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; - dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 32b1cd0bca1f..d9ec7d9bb1c4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -125,10 +125,6 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map); he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map); - he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); - he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); - he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map); - he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map); memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & From 0fda6d7bb5a29b241fba8d37b92567c6bec79655 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 30 Mar 2021 01:25:00 +0800 Subject: [PATCH 101/188] mt76: report Rx timestamp Frame reception timestamp (low 32-bits) that indicates the value of the local TSF timer value at the time the first bit of the MAC header in the received frame (PPDU unit) arriving at the MAC. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/agg-rx.c | 6 ++-- drivers/net/wireless/mediatek/mt76/mac80211.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt76.h | 3 +- .../net/wireless/mediatek/mt76/mt7603/init.c | 3 ++ .../net/wireless/mediatek/mt76/mt7603/mac.c | 31 ++++++++++-------- .../wireless/mediatek/mt76/mt7603/mt7603.h | 2 +- .../net/wireless/mediatek/mt76/mt7615/init.c | 3 ++ .../net/wireless/mediatek/mt76/mt7615/mac.c | 32 ++++++++++--------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 +- .../net/wireless/mediatek/mt76/mt7915/init.c | 3 ++ .../net/wireless/mediatek/mt76/mt7915/mac.c | 29 +++++++++-------- .../wireless/mediatek/mt76/mt7915/mt7915.h | 2 +- .../net/wireless/mediatek/mt76/mt7921/init.c | 3 ++ .../net/wireless/mediatek/mt76/mt7921/mac.c | 29 +++++++++-------- .../wireless/mediatek/mt76/mt7921/mt7921.h | 2 +- 15 files changed, 89 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 144e8a8910ba..72622220051b 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -76,9 +76,9 @@ mt76_rx_aggr_check_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames) nframes--; status = (struct mt76_rx_status *)skb->cb; - if (!time_after(jiffies, - status->reorder_time + - mt76_aggr_tid_to_timeo(tid->num))) + if (!time_after32(jiffies, + status->reorder_time + + mt76_aggr_tid_to_timeo(tid->num))) continue; mt76_rx_aggr_release_frames(tid, frames, status->seqno); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index ef31026ac9d7..29ef15ec22fe 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -754,6 +754,8 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, status->signal = mstat.signal; status->chains = mstat.chains; status->ampdu_reference = mstat.ampdu_ref; + status->device_timestamp = mstat.timestamp; + status->mactime = mstat.timestamp; BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb)); BUILD_BUG_ON(sizeof(status->chain_signal) != diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index b09b0f5ffd6d..d121c176c37c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -498,9 +498,10 @@ struct mt76_rx_status { u16 wcid_idx; }; - unsigned long reorder_time; + u32 reorder_time; u32 ampdu_ref; + u32 timestamp; u8 iv[6]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index f0b879c3eba8..e1b2cfa56074 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -548,6 +548,9 @@ int mt7603_register_device(struct mt7603_dev *dev) hw->max_report_rates = 7; hw->max_rate_tries = 11; + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + hw->sta_data_size = sizeof(struct mt7603_sta); hw->vif_data_size = sizeof(struct mt7603_vif); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index c29b60a87819..e3a9dd6fbd87 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -532,20 +532,6 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; } - if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | - MT_RXD2_NORMAL_NON_AMPDU))) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (dev->rx_ampdu_ts != rxd[12]) { - if (!++dev->ampdu_ref) - dev->ampdu_ref++; - } - dev->rx_ampdu_ts = rxd[12]; - - status->ampdu_ref = dev->ampdu_ref; - } - remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) @@ -579,6 +565,23 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) return -EINVAL; } if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | + MT_RXD2_NORMAL_NON_AMPDU))) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (dev->rx_ampdu_ts != status->timestamp) { + if (!++dev->ampdu_ref) + dev->ampdu_ref++; + } + dev->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = dev->ampdu_ref; + } + rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index b787c56fd8d6..1df5b9fed2bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -120,7 +120,7 @@ struct mt7603_dev { unsigned long last_cca_adj; u32 ampdu_ref; - __le32 rx_ampdu_ts; + u32 rx_ampdu_ts; u8 rssi_offset[3]; u8 slottime; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 857fb4918975..1e418740c17b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -333,6 +333,9 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) hw->max_rate_tries = 11; hw->netdev_features = NETIF_F_RXCSUM; + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + phy->slottime = 9; hw->sta_data_size = sizeof(struct mt7615_sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 6a1395de3066..005c2829d3df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -235,7 +235,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; - __le32 rxd12 = rxd[12]; bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false; int phy_idx; int i, idx; @@ -329,6 +328,23 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) } if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | + MT_RXD2_NORMAL_NON_AMPDU))) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != status->timestamp) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = phy->ampdu_ref; + } + rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -372,20 +388,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (!sband->channels) return -EINVAL; - if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | - MT_RXD2_NORMAL_NON_AMPDU))) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (phy->rx_ampdu_ts != rxd12) { - if (!++phy->ampdu_ref) - phy->ampdu_ref++; - } - phy->rx_ampdu_ts = rxd12; - - status->ampdu_ref = phy->ampdu_ref; - } - if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { u32 rxdg0 = le32_to_cpu(rxd[0]); u32 rxdg1 = le32_to_cpu(rxd[1]); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index dbabdeef4e0b..6a50338ec9f5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -168,7 +168,7 @@ struct mt7615_phy { u8 rdd_state; int dfs_state; - __le32 rx_ampdu_ts; + u32 rx_ampdu_ts; u32 ampdu_ref; struct mib_stats mib; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 261f5ab23721..983ec5276f46 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -96,6 +96,9 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; hw->netdev_features = NETIF_F_RXCSUM; + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + phy->slottime = 9; hw->sta_data_size = sizeof(struct mt7915_sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 0924ae074db2..11596e74712a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -389,19 +389,6 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; } - if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (phy->rx_ampdu_ts != rxd[14]) { - if (!++phy->ampdu_ref) - phy->ampdu_ref++; - } - phy->rx_ampdu_ts = rxd[14]; - - status->ampdu_ref = phy->ampdu_ref; - } - remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) @@ -440,6 +427,22 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) } if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != status->timestamp) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = phy->ampdu_ref; + } + rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 1160d1bf8a7c..455c84cd99c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -142,7 +142,7 @@ struct mt7915_phy { u8 rdd_state; int dfs_state; - __le32 rx_ampdu_ts; + u32 rx_ampdu_ts; u32 ampdu_ref; struct mib_stats mib; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index b34db6e8d0ae..5bb0a7b9e9e5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -77,6 +77,9 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + phy->slottime = 9; hw->sta_data_size = sizeof(struct mt7921_sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 36eaa9d97f64..b507f3917830 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -370,19 +370,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; } - if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (phy->rx_ampdu_ts != rxd[14]) { - if (!++phy->ampdu_ref) - phy->ampdu_ref++; - } - phy->rx_ampdu_ts = rxd[14]; - - status->ampdu_ref = phy->ampdu_ref; - } - remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) @@ -414,6 +401,22 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) } if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != status->timestamp) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = phy->ampdu_ref; + } + rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index e4211b049040..e3d83d3d954c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -132,7 +132,7 @@ struct mt7921_phy { s16 coverage_class; u8 slottime; - __le32 rx_ampdu_ts; + u32 rx_ampdu_ts; u32 ampdu_ref; struct mib_stats mib; From 6d88629e158dc1a3f58a0f9b528fe0057d44e8f6 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 9 Apr 2021 00:36:31 +0800 Subject: [PATCH 102/188] mt76: mt7915: add mmio.c Add mmio.c in order to use mt76_bus_ops throughout the driver. It will be also shared with the future APSoC revision. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7915/Makefile | 2 +- .../net/wireless/mediatek/mt76/mt7915/dma.c | 108 ------------- .../net/wireless/mediatek/mt76/mt7915/init.c | 11 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 16 +- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +-- .../net/wireless/mediatek/mt76/mt7915/mmio.c | 152 ++++++++++++++++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 75 +-------- .../net/wireless/mediatek/mt76/mt7915/pci.c | 13 +- 8 files changed, 177 insertions(+), 218 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mmio.c diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile index cc2054dffa98..40c8061787e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_MT7915E) += mt7915e.o mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ - debugfs.o + debugfs.o mmio.o mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 3c961bf55e97..9fe09870f8f0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -110,121 +110,13 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev) __mt7915_dma_prefetch(dev, MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE); } -static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr) -{ - static const struct { - u32 phys; - u32 mapped; - u32 size; - } fixed_map[] = { - { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */ - { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */ - { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ - { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */ - { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */ - { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */ - { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ - { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ - { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */ - { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */ - { 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */ - { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */ - { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */ - { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ - { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ - { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ - { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ - { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ - { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ - { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ - { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ - { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ - { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ - { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ - { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ - { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ - { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ - { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ - { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ - { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ - { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ - { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ - { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ - { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ - { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ - { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ - { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ - { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ - }; - int i; - - if (addr < 0x100000) - return addr; - - for (i = 0; i < ARRAY_SIZE(fixed_map); i++) { - u32 ofs; - - if (addr < fixed_map[i].phys) - continue; - - ofs = addr - fixed_map[i].phys; - if (ofs > fixed_map[i].size) - continue; - - return fixed_map[i].mapped + ofs; - } - - if ((addr >= 0x18000000 && addr < 0x18c00000) || - (addr >= 0x70000000 && addr < 0x78000000) || - (addr >= 0x7c000000 && addr < 0x7c400000)) - return mt7915_reg_map_l1(dev, addr); - - return mt7915_reg_map_l2(dev, addr); -} - -static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset) -{ - struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - u32 addr = __mt7915_reg_addr(dev, offset); - - return dev->bus_ops->rr(mdev, addr); -} - -static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val) -{ - struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - u32 addr = __mt7915_reg_addr(dev, offset); - - dev->bus_ops->wr(mdev, addr, val); -} - -static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) -{ - struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - u32 addr = __mt7915_reg_addr(dev, offset); - - return dev->bus_ops->rmw(mdev, addr, mask, val); -} - int mt7915_dma_init(struct mt7915_dev *dev) { /* Increase buffer size to receive large VHT/HE MPDUs */ - struct mt76_bus_ops *bus_ops; int rx_buf_size = MT_RX_BUF_SIZE * 2; u32 hif1_ofs = 0; int ret; - dev->bus_ops = dev->mt76.bus; - bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), - GFP_KERNEL); - if (!bus_ops) - return -ENOMEM; - - bus_ops->rr = mt7915_rr; - bus_ops->wr = mt7915_wr; - bus_ops->rmw = mt7915_rmw; - dev->mt76.bus = bus_ops; - mt76_dma_attach(&dev->mt76); if (dev->hif2) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 983ec5276f46..2732899689fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -302,7 +302,6 @@ static void mt7915_init_work(struct work_struct *work) static void mt7915_wfsys_reset(struct mt7915_dev *dev) { u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; - u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); #define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) #define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) @@ -334,7 +333,7 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev) } /* wfsys reset won't clear host registers */ - mt76_clear(dev, reg, MT_TOP_MISC_FW_STATE); + mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE); msleep(100); } @@ -342,7 +341,6 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev) static int mt7915_init_hardware(struct mt7915_dev *dev) { int ret, idx; - u32 val; mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); @@ -350,12 +348,11 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) spin_lock_init(&dev->token_lock); idr_init(&dev->token); - dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); - - val = mt76_rr(dev, mt7915_reg_map_l1(dev, MT_TOP_MISC)); + dev->dbdc_support = !!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)); /* If MCU was already running, it is likely in a bad state */ - if (FIELD_GET(MT_TOP_MISC_FW_STATE, val) > FW_STATE_FW_DOWNLOAD) + if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) > + FW_STATE_FW_DOWNLOAD) mt7915_wfsys_reset(dev); ret = mt7915_dma_init(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 11596e74712a..3f3bfead1ce7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1300,8 +1300,8 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy) bool ext_phy = phy != &dev->phy; u32 reg = MT_WF_PHY_RX_CTRL1(ext_phy); - mt7915_l2_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); - mt7915_l2_set(dev, reg, BIT(11) | BIT(9)); + mt76_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); + mt76_set(dev, reg, BIT(11) | BIT(9)); } void mt7915_mac_reset_counters(struct mt7915_phy *phy) @@ -1394,12 +1394,12 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy) { - mt7915_l2_set(dev, MT_WF_PHY_RXTD12(ext_phy), - MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | - MT_WF_PHY_RXTD12_IRPI_SW_CLR); + mt76_set(dev, MT_WF_PHY_RXTD12(ext_phy), + MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | + MT_WF_PHY_RXTD12_IRPI_SW_CLR); - mt7915_l2_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), - FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); + mt76_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), + FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); } static u8 @@ -1414,7 +1414,7 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx) u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support)); for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { - val = mt7915_l2_rr(dev, reg); + val = mt76_rr(dev, reg); sum += val * nf_power[i]; n += val; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 639f65d63add..0b739ed8ce33 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2542,11 +2542,9 @@ static int mt7915_mcu_start_patch(struct mt7915_dev *dev) static int mt7915_driver_own(struct mt7915_dev *dev) { - u32 reg = mt7915_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); - - mt76_wr(dev, reg, MT_TOP_LPCR_HOST_DRV_OWN); - if (!mt76_poll_msec(dev, reg, MT_TOP_LPCR_HOST_FW_OWN, - 0, 500)) { + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_DRV_OWN); + if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND0, + MT_TOP_LPCR_HOST_FW_OWN, 0, 500)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } @@ -2784,7 +2782,6 @@ out: static int mt7915_load_firmware(struct mt7915_dev *dev) { - u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); int ret; ret = mt7915_load_patch(dev); @@ -2795,7 +2792,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev) if (ret) return ret; - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, + if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_WACPU_RDY), 1000)) { dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); @@ -2883,18 +2880,15 @@ int mt7915_mcu_init(struct mt7915_dev *dev) void mt7915_mcu_exit(struct mt7915_dev *dev) { - u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); - __mt76_mcu_restart(&dev->mt76); - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, + if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD), 1000)) { dev_err(dev->mt76.dev, "Failed to exit mcu\n"); return; } - reg = mt7915_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); - mt76_wr(dev, reg, MT_TOP_LPCR_HOST_FW_OWN); + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_FW_OWN); skb_queue_purge(&dev->mt76.mcu.res_q); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c new file mode 100644 index 000000000000..af712a936ef6 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7915.h" + +static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr) +{ + u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); + u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); + + mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base); + /* use read to push write */ + mt76_rr(dev, MT_HIF_REMAP_L1); + + return MT_HIF_REMAP_BASE_L1 + offset; +} + +static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr) +{ + u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); + u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); + + mt76_rmw_field(dev, MT_HIF_REMAP_L2, MT_HIF_REMAP_L2_MASK, base); + /* use read to push write */ + mt76_rr(dev, MT_HIF_REMAP_L2); + + return MT_HIF_REMAP_BASE_L2 + offset; +} + +static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr) +{ + static const struct { + u32 phys; + u32 mapped; + u32 size; + } fixed_map[] = { + { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */ + { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */ + { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */ + { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */ + { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */ + { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ + { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ + { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */ + { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */ + { 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */ + { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */ + { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */ + { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ + { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ + { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ + { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ + { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ + { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ + { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ + { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ + { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ + { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ + { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ + { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ + { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ + { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ + { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ + { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ + { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ + }; + int i; + + if (addr < 0x100000) + return addr; + + for (i = 0; i < ARRAY_SIZE(fixed_map); i++) { + u32 ofs; + + if (addr < fixed_map[i].phys) + continue; + + ofs = addr - fixed_map[i].phys; + if (ofs > fixed_map[i].size) + continue; + + return fixed_map[i].mapped + ofs; + } + + if ((addr >= 0x18000000 && addr < 0x18c00000) || + (addr >= 0x70000000 && addr < 0x78000000) || + (addr >= 0x7c000000 && addr < 0x7c400000)) + return mt7915_reg_map_l1(dev, addr); + + return mt7915_reg_map_l2(dev, addr); +} + +static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + u32 addr = __mt7915_reg_addr(dev, offset); + + return dev->bus_ops->rr(mdev, addr); +} + +static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + u32 addr = __mt7915_reg_addr(dev, offset); + + dev->bus_ops->wr(mdev, addr, val); +} + +static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + u32 addr = __mt7915_reg_addr(dev, offset); + + return dev->bus_ops->rmw(mdev, addr, mask, val); +} + +int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq) +{ + struct mt76_bus_ops *bus_ops; + struct mt7915_dev *dev; + + dev = container_of(mdev, struct mt7915_dev, mt76); + mt76_mmio_init(&dev->mt76, mem_base); + + dev->bus_ops = dev->mt76.bus; + bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), + GFP_KERNEL); + if (!bus_ops) + return -ENOMEM; + + bus_ops->rr = mt7915_rr; + bus_ops->wr = mt7915_wr; + bus_ops->rmw = mt7915_rmw; + dev->mt76.bus = bus_ops; + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + mt76_wr(dev, MT_INT_MASK_CSR, 0); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 455c84cd99c2..dbc70c0d6668 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -394,80 +394,6 @@ static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask) mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); } -static inline u32 -mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr) -{ - u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); - u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); - - mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base); - /* use read to push write */ - mt76_rr(dev, MT_HIF_REMAP_L1); - - return MT_HIF_REMAP_BASE_L1 + offset; -} - -static inline u32 -mt7915_l1_rr(struct mt7915_dev *dev, u32 addr) -{ - return mt76_rr(dev, mt7915_reg_map_l1(dev, addr)); -} - -static inline void -mt7915_l1_wr(struct mt7915_dev *dev, u32 addr, u32 val) -{ - mt76_wr(dev, mt7915_reg_map_l1(dev, addr), val); -} - -static inline u32 -mt7915_l1_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val) -{ - val |= mt7915_l1_rr(dev, addr) & ~mask; - mt7915_l1_wr(dev, addr, val); - - return val; -} - -#define mt7915_l1_set(dev, addr, val) mt7915_l1_rmw(dev, addr, 0, val) -#define mt7915_l1_clear(dev, addr, val) mt7915_l1_rmw(dev, addr, val, 0) - -static inline u32 -mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr) -{ - u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); - u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); - - mt76_rmw_field(dev, MT_HIF_REMAP_L2, MT_HIF_REMAP_L2_MASK, base); - /* use read to push write */ - mt76_rr(dev, MT_HIF_REMAP_L2); - - return MT_HIF_REMAP_BASE_L2 + offset; -} - -static inline u32 -mt7915_l2_rr(struct mt7915_dev *dev, u32 addr) -{ - return mt76_rr(dev, mt7915_reg_map_l2(dev, addr)); -} - -static inline void -mt7915_l2_wr(struct mt7915_dev *dev, u32 addr, u32 val) -{ - mt76_wr(dev, mt7915_reg_map_l2(dev, addr), val); -} - -static inline u32 -mt7915_l2_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val) -{ - val |= mt7915_l2_rr(dev, addr) & ~mask; - mt7915_l2_wr(dev, addr, val); - - return val; -} - -#define mt7915_l2_set(dev, addr, val) mt7915_l2_rmw(dev, addr, 0, val) -#define mt7915_l2_clear(dev, addr, val) mt7915_l2_rmw(dev, addr, val, 0) - 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); @@ -486,6 +412,7 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7915_mac_work(struct work_struct *work); void mt7915_mac_reset_work(struct work_struct *work); void mt7915_mac_sta_rc_work(struct work_struct *work); +int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq); 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, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index 13880cc9c9e8..75769595d1e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -201,7 +201,7 @@ static void mt7915_pci_init_hif2(struct mt7915_dev *dev) } /* master switch of PCIe tnterrupt enable */ - mt7915_l1_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); } static int mt7915_pci_hif2_probe(struct pci_dev *pdev) @@ -274,15 +274,12 @@ static int mt7915_pci_probe(struct pci_dev *pdev, if (ret) goto error; - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) | - (mt7915_l1_rr(dev, MT_HW_REV) & 0xff); - dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - - mt76_wr(dev, MT_INT_MASK_CSR, 0); + ret = mt7915_mmio_init(mdev, pcim_iomap_table(pdev)[0], pdev->irq); + if (ret) + goto error; /* master switch of PCIe tnterrupt enable */ - mt7915_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); From 30ad36214ab52a5eb3475e012e6bf327f843aa48 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 9 Apr 2021 00:36:32 +0800 Subject: [PATCH 103/188] mt76: mt7615: add missing SPDX tag in mmio.c Resolve the following checkpatch.pl script warning: WARNING: Missing or malformed SPDX-License-Identifier tag in line 1 Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mmio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index a7f92fa0488f..eaa22752e7cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + #include #include #include From 66978204f71b36c2c0240e50c5789fae2d8b87a6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 Apr 2021 16:58:50 +0200 Subject: [PATCH 104/188] mt76: mt7615: always add rx header translation tlv when adding stations Ensures that header translation is disabled for interfaces that do not support it. Fixes: d4b98c63d7a7 ("mt76: mt7615: add support for rx decapsulation offload") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 6 +----- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 6ca9e9840399..9b9f8d88e9bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1008,6 +1008,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta, NULL, wtbl_hdr); + mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, &msta->wcid, NULL, + wtbl_hdr); } cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE; @@ -1136,7 +1138,7 @@ int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev, if (IS_ERR(wtbl_hdr)) return PTR_ERR(wtbl_hdr); - mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, &msta->wcid, NULL, wtbl_hdr); return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 4892728ad9bb..443ec0a8bb7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -393,11 +393,9 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif, } void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct mt76_wcid *wcid, void *sta_wtbl, void *wtbl_tlv) { - struct mt76_wcid *wcid; struct wtbl_hdr_trans *htr; struct tlv *tlv; @@ -405,8 +403,6 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, sizeof(*htr), wtbl_tlv, sta_wtbl); htr = (struct wtbl_hdr_trans *)tlv; - - wcid = (struct mt76_wcid *)sta->drv_priv; htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 6f9b7807305a..587097450416 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -937,8 +937,7 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, void *sta_wtbl, void *wtbl_tlv); void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct mt76_wcid *wcid, void *sta_wtbl, void *wtbl_tlv); void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_sta *sta, From 2afd17b4d0fc15cba0144e7a4c26549b0e829ce9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 11 Apr 2021 21:03:45 +0200 Subject: [PATCH 105/188] mt76: mt7921: introduce MCU_EVENT_LP_INFO event parsing Report trace event related to MCU_EVENT_LP_INFO that is sent by the mcu when it is ready to enter in deep sleep state Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7921/Makefile | 4 +- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 19 +++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.h | 1 + .../mediatek/mt76/mt7921/mt7921_trace.h | 51 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/trace.c | 12 +++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/trace.c diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index 09d1446ad933..e531666f9fb4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -2,4 +2,6 @@ obj-$(CONFIG_MT7921E) += mt7921e.o -mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o +CFLAGS_trace.o := -I$(src) + +mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o trace.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index b233b12860ef..7d45e8795e15 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -4,6 +4,7 @@ #include #include #include "mt7921.h" +#include "mt7921_trace.h" #include "mcu.h" #include "mac.h" @@ -498,6 +499,20 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) } } +static void +mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb) +{ + struct mt7921_mcu_lp_event { + u8 state; + u8 reserved[3]; + } __packed * event; + + skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + event = (struct mt7921_mcu_lp_event *)skb->data; + + trace_lp_event(dev, event->state); +} + static void mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) { @@ -521,6 +536,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) mt76_connac_mcu_coredump_event(&dev->mt76, skb, &dev->coredump); return; + case MCU_EVENT_LP_INFO: + mt7921_mcu_low_power_event(dev, skb); + break; default: break; } @@ -543,6 +561,7 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) rxd->eid == MCU_EVENT_SCAN_DONE || rxd->eid == MCU_EVENT_DBG_MSG || rxd->eid == MCU_EVENT_COREDUMP || + rxd->eid == MCU_EVENT_LP_INFO || !rxd->seq) mt7921_mcu_rx_unsolicited_event(dev, skb); else diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index af8b42983a00..13e125f32283 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -79,6 +79,7 @@ struct mt7921_uni_txd { /* event table */ enum { MCU_EVENT_REG_ACCESS = 0x05, + MCU_EVENT_LP_INFO = 0x07, MCU_EVENT_SCAN_DONE = 0x0d, MCU_EVENT_BSS_ABSENCE = 0x11, MCU_EVENT_BSS_BEACON_LOSS = 0x13, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h new file mode 100644 index 000000000000..9bc4db67f352 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (C) 2021 Lorenzo Bianconi + */ + +#if !defined(__MT7921_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT7921_TRACE_H + +#include +#include "mt7921.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mt7921 + +#define MAXNAME 32 +#define DEV_ENTRY __array(char, wiphy_name, 32) +#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ + wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) +#define DEV_PR_FMT "%s" +#define DEV_PR_ARG __entry->wiphy_name +#define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready" + +TRACE_EVENT(lp_event, + TP_PROTO(struct mt7921_dev *dev, u8 lp_state), + + TP_ARGS(dev, lp_state), + + TP_STRUCT__entry( + DEV_ENTRY + __field(u8, lp_state) + ), + + TP_fast_assign( + DEV_ASSIGN; + __entry->lp_state = lp_state; + ), + + TP_printk( + DEV_PR_FMT " %s", + DEV_PR_ARG, LP_STATE_PR_ARG + ) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mt7921_trace + +#include diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/trace.c b/drivers/net/wireless/mediatek/mt76/mt7921/trace.c new file mode 100644 index 000000000000..4dc3c7b89ebd --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/trace.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2021 Lorenzo Bianconi + */ + +#include + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "mt7921_trace.h" + +#endif From 481fc927c8289919cc0be58666fcd1b7da187a0c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 12 Apr 2021 14:25:54 +0200 Subject: [PATCH 106/188] mt76: mt7921: add rcu section in mt7921_mcu_tx_rate_report Introduce rcu section in mt7921_mcu_tx_rate_report before dereferencing wcid pointer otherwise loockdep will report the following issue: [ 115.245740] ============================= [ 115.245754] WARNING: suspicious RCU usage [ 115.245771] 5.10.20 #0 Not tainted [ 115.245784] ----------------------------- [ 115.245816] other info that might help us debug this: [ 115.245830] rcu_scheduler_active = 2, debug_locks = 1 [ 115.245845] 3 locks held by kworker/u4:1/20: [ 115.245858] #0: ffffff80065ab138 ((wq_completion)phy0){+.+.}-{0:0}, at: process_one_work+0x1f8/0x6b8 [ 115.245948] #1: ffffffc01198bdd8 ((work_completion)(&(&dev->mphy.mac_work)->work)){+.+.}-{0:0}, at: process_one_8 [ 115.246027] #2: ffffff8006543ce8 (&dev->mutex#2){+.+.}-{3:3}, at: mt7921_mac_work+0x60/0x2b0 [mt7921e] [ 115.246125] [ 115.246125] stack backtrace: [ 115.246142] CPU: 1 PID: 20 Comm: kworker/u4:1 Not tainted 5.10.20 #0 [ 115.246152] Hardware name: MediaTek MT7622 RFB1 board (DT) [ 115.246168] Workqueue: phy0 mt7921_mac_work [mt7921e] [ 115.246188] Call trace: [ 115.246201] dump_backtrace+0x0/0x1a8 [ 115.246213] show_stack+0x14/0x30 [ 115.246228] dump_stack+0xec/0x134 [ 115.246240] lockdep_rcu_suspicious+0xcc/0xdc [ 115.246255] mt7921_get_wtbl_info+0x2a4/0x310 [mt7921e] [ 115.246269] mt7921_mac_work+0x284/0x2b0 [mt7921e] [ 115.246281] process_one_work+0x2a0/0x6b8 [ 115.246293] worker_thread+0x40/0x440 [ 115.246305] kthread+0x144/0x148 [ 115.246317] ret_from_fork+0x10/0x18 Fixes: 1c099ab44727c ("mt76: mt7921: add MCU support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 7d45e8795e15..aa55667b6ed7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -413,9 +413,12 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb, if (wlan_idx >= MT76_N_WCIDS) return; + + rcu_read_lock(); + wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); if (!wcid) - return; + goto out; msta = container_of(wcid, struct mt7921_sta, wcid); stats = &msta->stats; @@ -423,6 +426,8 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb, /* current rate */ mt7921_mcu_tx_rate_parse(mphy, &peer, &rate, curr); stats->tx_rate = rate; +out: + rcu_read_unlock(); } static void From 7686fd52b8757aaedb4cf3b38bf02d1911674545 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 30 Mar 2021 16:24:49 +0300 Subject: [PATCH 107/188] iwlwifi: mvm: enable TX on new CSA channel before disconnecting When moving to the new channel, we block TX until we hear the first beacon. if it is not heard, we proceed to disconnect. Since TX is blocked (without mac80211 being aware of it) the frame is stuck, resulting with queue hang. Instead, reenable TX before reporting on the connection loss. As we are on the new channel, there is no problem with that, even if the original CSA had quiet mode. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.eb4f2ff1b863.Ib16238106b33d58b2b7688dc6297018b915ecef4@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 0b012f8c9eb2..1418a6438635 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -151,6 +151,16 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm, if (errmsg) IWL_ERR(mvm, "%s\n", errmsg); + if (mvmvif->csa_bcn_pending) { + struct iwl_mvm_sta *mvmsta; + + rcu_read_lock(); + mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id); + if (!WARN_ON(!mvmsta)) + iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false); + rcu_read_unlock(); + } + iwl_mvm_connection_loss(mvm, vif, errmsg); return true; } From 72bc934cb393d9aa0a3a73026c020da36e817fa1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2021 16:24:50 +0300 Subject: [PATCH 108/188] iwlwifi: pcie: avoid unnecessarily taking spinlock Most devices don't set the apmg_wake_up_wa flag, so we don't do anything for them. Avoid taking the spinlock for every command unless the device needs this workaround. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.1ab60af3f318.I51cc202f68a2a953223e70c3e8610343412961b6@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 54 +++++++++----------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 7ae32491b5da..5ce61fb469cd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -181,16 +181,20 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - lockdep_assert_held(&trans_pcie->reg_lock); - if (!trans->trans_cfg->base_params->apmg_wake_up_wa) return; - if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) + + spin_lock(&trans_pcie->reg_lock); + + if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) { + spin_unlock(&trans_pcie->reg_lock); return; + } trans_pcie->cmd_hold_nic_awake = false; __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + spin_unlock(&trans_pcie->reg_lock); } /* @@ -198,7 +202,6 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) */ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq = trans->txqs.txq[txq_id]; if (!txq) { @@ -222,12 +225,9 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) iwl_txq_free_tfd(trans, txq); txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr); - if (txq->read_ptr == txq->write_ptr) { - spin_lock(&trans_pcie->reg_lock); - if (txq_id == trans->txqs.cmd.q_id) - iwl_pcie_clear_cmd_in_flight(trans); - spin_unlock(&trans_pcie->reg_lock); - } + if (txq->read_ptr == txq->write_ptr && + txq_id == trans->txqs.cmd.q_id) + iwl_pcie_clear_cmd_in_flight(trans); } while (!skb_queue_empty(&txq->overflow_q)) { @@ -629,22 +629,23 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, const struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int ret; - - lockdep_assert_held(&trans_pcie->reg_lock); + int ret = 0; /* Make sure the NIC is still alive in the bus */ if (test_bit(STATUS_TRANS_DEAD, &trans->status)) return -ENODEV; + if (!trans->trans_cfg->base_params->apmg_wake_up_wa) + return 0; + + spin_lock(&trans_pcie->reg_lock); /* * wake up the NIC to make sure that the firmware will see the host * command - we will let the NIC sleep once all the host commands * returned. This needs to be done only on NICs that have - * apmg_wake_up_wa set. + * apmg_wake_up_wa set (see above.) */ - if (trans->trans_cfg->base_params->apmg_wake_up_wa && - !trans_pcie->cmd_hold_nic_awake) { + if (!trans_pcie->cmd_hold_nic_awake) { __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); @@ -657,12 +658,14 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); IWL_ERR(trans, "Failed to wake NIC for hcmd\n"); - return -EIO; + ret = -EIO; + } else { + trans_pcie->cmd_hold_nic_awake = true; } - trans_pcie->cmd_hold_nic_awake = true; } + spin_unlock(&trans_pcie->reg_lock); - return 0; + return ret; } /* @@ -674,7 +677,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, */ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq = trans->txqs.txq[txq_id]; int nfreed = 0; u16 r; @@ -705,12 +707,8 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) } } - if (txq->read_ptr == txq->write_ptr) { - /* BHs are also disabled due to txq->lock */ - spin_lock(&trans_pcie->reg_lock); + if (txq->read_ptr == txq->write_ptr) iwl_pcie_clear_cmd_in_flight(trans); - spin_unlock(&trans_pcie->reg_lock); - } iwl_txq_progress(txq); } @@ -914,7 +912,6 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id]; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -1161,19 +1158,16 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, if (txq->read_ptr == txq->write_ptr && txq->wd_timeout) mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); - spin_lock(&trans_pcie->reg_lock); ret = iwl_pcie_set_cmd_in_flight(trans, cmd); if (ret < 0) { idx = ret; - goto unlock_reg; + goto out; } /* Increment and update queue's write index */ txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr); iwl_pcie_txq_inc_wr_ptr(trans, txq); - unlock_reg: - spin_unlock(&trans_pcie->reg_lock); out: spin_unlock_irqrestore(&txq->lock, flags); free_dup_buf: From 416dde0f83a87f35fa8ca44e0837a55903b46ffe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2021 16:24:51 +0300 Subject: [PATCH 109/188] iwlwifi: pcie: normally grab NIC access for inflight-hcmd We currently have a special, separate, code path to acquire NIC access for the in-flight host-command workaround on 7000 series hardware. However, the normal code path here has grown a number of additional workarounds/semantics over time, such as reprobing the device if things fail. Rather than try to replicate any of this logic, call the normal grab_nic_access logic for the workaround. This changes the spinlock to _bh, but that's OK since it's just redundant, we already have soft-IRQs disabled when we get here, and so didn't (have to) do it again. Since it's only for commands there's however no point in making the code more complex just to not use _bh here. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.d196fc6ffb23.Idc1ce3ce9fed9178beee7e5409bc669f79b06a0d@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 31 +++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 5ce61fb469cd..b07194b74d97 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -629,7 +629,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, const struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int ret = 0; /* Make sure the NIC is still alive in the bus */ if (test_bit(STATUS_TRANS_DEAD, &trans->status)) @@ -638,34 +637,24 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, if (!trans->trans_cfg->base_params->apmg_wake_up_wa) return 0; - spin_lock(&trans_pcie->reg_lock); /* * wake up the NIC to make sure that the firmware will see the host * command - we will let the NIC sleep once all the host commands * returned. This needs to be done only on NICs that have * apmg_wake_up_wa set (see above.) */ - if (!trans_pcie->cmd_hold_nic_awake) { - __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + if (!iwl_trans_grab_nic_access(trans)) + return -EIO; - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, - (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), - 15000); - if (ret < 0) { - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - IWL_ERR(trans, "Failed to wake NIC for hcmd\n"); - ret = -EIO; - } else { - trans_pcie->cmd_hold_nic_awake = true; - } - } - spin_unlock(&trans_pcie->reg_lock); + /* + * In iwl_trans_grab_nic_access(), we've acquired the reg_lock. + * There, we also returned immediately if cmd_hold_nic_awake is + * already true, so it's OK to unconditionally set it to true. + */ + trans_pcie->cmd_hold_nic_awake = true; + spin_unlock_bh(&trans_pcie->reg_lock); - return ret; + return 0; } /* From 2360acbd5e22d95d1a8fcd096478198c572d9b85 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 30 Mar 2021 16:24:52 +0300 Subject: [PATCH 110/188] iwlwifi: mvm: don't allow CSA if we haven't been fully associated "Fully associated" means that we heard a beacon with the DTIM information and the firmware is configured to track the beacons. Since the firmware needs to track the beacons for the CSA, we can't configure the firmware for CSA before it knows when the beacons are expected otherwise we'd get ASSERT 301D. If we are required to start CSA before we told the firmware when the beacons are expected to arrive, just report a failure and let mac80211 disconnect. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.9adaedeb59e4.Idaad6aaf3f9759d023b8e00b10064915c0db9aa3@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index baf7404c137d..9ed6e2783cc4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -4610,6 +4610,16 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, break; case NL80211_IFTYPE_STATION: + /* + * We haven't configured the firmware to be associated yet since + * we don't know the dtim period. In this case, the firmware can't + * track the beacons. + */ + if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) { + ret = -EBUSY; + goto out_unlock; + } + if (chsw->delay > IWL_MAX_CSA_BLOCK_TX) schedule_delayed_work(&mvmvif->csa_work, 0); From 2be05dfd9c3f86c66ebcfd7b2a01d07c7e0158dd Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Tue, 30 Mar 2021 16:24:53 +0300 Subject: [PATCH 111/188] iwlwifi: pcie: Add support for Bz Family Add support for different combinations of Bz and CRFs. Note: As of now we do not know the exact values for ltr_delay and xtal_latency, so for now use the worst case scenario values until the actual values are clarified. Signed-off-by: Matti Gottlieb Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.caac8d996532.I6a22d6decb106cd50d7954b19236b69d685dcc39@changeid Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/cfg/22000.c | 58 +++++++++++++++++++ .../net/wireless/intel/iwlwifi/iwl-config.h | 6 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 24 ++++++++ 3 files changed, 88 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 0a0e25a3c681..d4f3eee81db7 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -48,6 +48,10 @@ #define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0-" #define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0-" #define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-" +#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0-" +#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-" +#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-" +#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-" #define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" @@ -91,6 +95,14 @@ IWL_MA_A_MR_A_FW_PRE __stringify(api) ".ucode" #define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \ IWL_SNJ_A_MR_A_FW_PRE __stringify(api) ".ucode" +#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_BZ_A_HR_B_FW_PRE __stringify(api) ".ucode" +#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_BZ_A_GF_A_FW_PRE __stringify(api) ".ucode" +#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \ + IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode" +#define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \ + IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode" static const struct iwl_base_params iwl_22000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -357,6 +369,20 @@ const struct iwl_cfg_trans_params iwl_ma_trans_cfg = { .umac_prph_offset = 0x300000 }; +const struct iwl_cfg_trans_params iwl_bz_trans_cfg = { + .device_family = IWL_DEVICE_FAMILY_AX210, + .base_params = &iwl_ax210_base_params, + .mq_rx_supported = true, + .use_tfh = true, + .rf_id = true, + .gen2 = true, + .integrated = true, + .umac_prph_offset = 0x300000, + .xtal_latency = 12000, + .low_latency_xtal = true, + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, +}; + const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101"; const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; @@ -719,6 +745,34 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; +const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = { + .fw_name_pre = IWL_BZ_A_HR_B_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = { + .fw_name_pre = IWL_BZ_A_GF_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = { + .fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = { + .fw_name_pre = IWL_BZ_A_MR_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); @@ -740,3 +794,7 @@ MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index c4f5da76f1c0..98335325e6b4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -416,6 +416,7 @@ struct iwl_cfg { #define IWL_CFG_MAC_TYPE_SNJ 0x42 #define IWL_CFG_MAC_TYPE_SOF 0x43 #define IWL_CFG_MAC_TYPE_MA 0x44 +#define IWL_CFG_MAC_TYPE_BZ 0x46 #define IWL_CFG_RF_TYPE_TH 0x105 #define IWL_CFG_RF_TYPE_TH1 0x108 @@ -477,6 +478,7 @@ extern const struct iwl_cfg_trans_params iwl_snj_trans_cfg; extern const struct iwl_cfg_trans_params iwl_so_trans_cfg; extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg; extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg; +extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg; extern const char iwl9162_name[]; extern const char iwl9260_name[]; extern const char iwl9260_1_name[]; @@ -612,6 +614,10 @@ extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0; extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0; extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0; extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0; +extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0; +extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0; +extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0; +extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0; #endif /* CONFIG_IWLMVM */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 558a0b2ef0fc..d7d91457f421 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -490,6 +490,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)}, {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)}, +/* Bz devices */ + {IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)}, #endif /* CONFIG_IWLMVM */ {0} @@ -1067,6 +1069,28 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name), +/* Bz */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_bz_a0_hr_b0, iwl_ax201_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_bz_a0_gf_a0, iwl_ax211_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, + iwl_cfg_bz_a0_gf4_a0, iwl_ax211_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_bz_a0_mr_a0, iwl_ma_name), + #endif /* CONFIG_IWLMVM */ }; From 39ab22c127aabc0634ea6fa268ffb9b938d31d9d Mon Sep 17 00:00:00 2001 From: ybaruch Date: Tue, 30 Mar 2021 16:24:54 +0300 Subject: [PATCH 112/188] iwlwifi: change step in so-gf struct change the step of iwlax210_2ax_cfg_so_jf_a0 to iwlax210_2ax_cfg_so_jf_b0 as it is on the wcd_fw-dev repository. Signed-off-by: ybaruch Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.e9a9d1da76bc.Ie964f37872bbb88d1a02094134f9a2c38faad884@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index d4f3eee81db7..8f98edcff572 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -604,7 +604,7 @@ const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; -const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = { +const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = { .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL_SO_A_JF_B_FW_PRE, IWL_DEVICE_AX210, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 98335325e6b4..f041f7f2160b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -596,7 +596,7 @@ extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0; extern const struct iwl_cfg killer1650x_2ax_cfg; extern const struct iwl_cfg killer1650w_2ax_cfg; extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg; -extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; +extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0; extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0; extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index d7d91457f421..7ae089234503 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1189,7 +1189,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { - iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_a0; + iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_b0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { iwl_trans->cfg = &iwlax211_2ax_cfg_so_gf_a0; From 20d04296b3cf1be81d5399a0ca12a38c8623dfe9 Mon Sep 17 00:00:00 2001 From: ybaruch Date: Tue, 30 Mar 2021 16:24:55 +0300 Subject: [PATCH 113/188] iwlwifi: change name to AX 211 and 411 family change the name of the ax211 and ax411. Signed-off-by: ybaruch Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.fc3218805052.I203f1a802338f59955bd511c90217f63b918390b@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 8f98edcff572..bea3d5f3014a 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -387,8 +387,8 @@ const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101"; const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203"; -const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6 AX211 160MHz"; -const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6 AX411 160MHz"; +const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; +const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz"; const char iwl_ma_name[] = "Intel(R) Wi-Fi 6"; const char iwl_ax200_killer_1650w_name[] = From a7ff1899a7bb97f2e396100c1be373d17a0ae836 Mon Sep 17 00:00:00 2001 From: ybaruch Date: Tue, 30 Mar 2021 16:24:56 +0300 Subject: [PATCH 114/188] iwlwifi: add 160Mhz to killer 1550 name change the name of 1550 killer device to 160Mhz. Signed-off-by: ybaruch Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.b87618a26ff8.Icf1d9c150ec108f30ce0e72c18b9350da6ae5087@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index c4164bf508e5..df1297358379 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -168,7 +168,7 @@ const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz"; const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz"; const char iwl9260_killer_1550_name[] = - "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)"; + "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz"; const char iwl9560_killer_1550i_name[] = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)"; const char iwl9560_killer_1550s_name[] = From d4626f91739b76633dbb3013e843e178c4a26618 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Tue, 30 Mar 2021 16:24:57 +0300 Subject: [PATCH 115/188] iwlwifi: pcie: clear only FH bits handle in the interrupt For simplicity we assume that msix has 2 IRQ lines one used for rx data called msix_non_share, and another used for one bit flags messages (alive, hw error, sw error, rx data flag) called msix_share. Every time the FW has data to send it puts it on the RX queue and HW turns on the flags in msix_share (inta_fw) indicating about rx data, and HW sends an interrupt a bit later to the msix_non_share _unless_ the msix_shared RX data bit was cleared. Currently in the code every time we get an msix_shared we clear all bits including rx data queue bits. So we can have a race ---------------------------------------------------- DRIVER | HW | FW ---------------------------------------------------- - send host cmd to FW | | | | - handle message | | and put a response | | on the RX queue | - RX flag on | | | - send alive msix | - alive flag on | | - interrupt | | msix_share driver | - handle msix_shared | | and clear all flags | | bits | | | - don't send an | | interrupt on | | msix_non_shared | | (driver cleared) | - driver timeout on | | waiting for host cmd | | respond | | | | ---------------------------------------------------- The change is to clear only the msi_shared flags that are handled in the msix_shared flow, which will cause the hardware to send an interrupt on the msix_non_share line as well, when it has data. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.a1cdda2fa270.I02a82312679f4541f30bb8db8747a797dbb70ee7@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 3 +++ drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 6ccde7e30211..db312abd2e09 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -578,6 +578,9 @@ enum msix_fh_int_causes { MSIX_FH_INT_CAUSES_FH_ERR = BIT(21), }; +/* The low 16 bits are for rx data queue indication */ +#define MSIX_FH_INT_CAUSES_DATA_QUEUE 0xffff + /* * Causes for the HW register interrupts */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 2bec97133119..0cbc79949982 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -2194,9 +2194,16 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry); struct iwl_trans *trans = trans_pcie->trans; struct isr_statistics *isr_stats = &trans_pcie->isr_stats; + u32 inta_fh_msk = ~MSIX_FH_INT_CAUSES_DATA_QUEUE; u32 inta_fh, inta_hw; bool polling = false; + if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX) + inta_fh_msk |= MSIX_FH_INT_CAUSES_Q0; + + if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS) + inta_fh_msk |= MSIX_FH_INT_CAUSES_Q1; + lock_map_acquire(&trans->sync_cmd_lockdep_map); spin_lock_bh(&trans_pcie->irq_lock); @@ -2205,7 +2212,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) /* * Clear causes registers to avoid being handling the same cause. */ - iwl_write32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh); + iwl_write32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh & inta_fh_msk); iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, inta_hw); spin_unlock_bh(&trans_pcie->irq_lock); From 48a5494d6a4cb5812f0640d9515f1876ffc7a013 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2021 16:24:58 +0300 Subject: [PATCH 116/188] iwlwifi: pcie: make cfg vs. trans_cfg more robust If we (for example) have a trans_cfg entry in the PCI IDs table, but then don't find a full cfg entry for it in the info table, we fall through to the code that treats the PCI ID table entry as a full cfg entry. This obviously causes crashes later, e.g. when trying to build the firmware name string. Avoid such crashes by using the low bit of the pointer as a tag for trans_cfg entries (automatically using a macro that checks the type when assigning) and then checking that before trying to use the data as a full entry - if it's just a partial entry at that point, fail. Since we're adding some macro magic, also check that the type is in fact either struct iwl_cfg_trans_params or struct iwl_cfg, failing compilation ("initializer element is not constant") if it isn't. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.6f69fe6e4128.I921d4ae20ef5276716baeeeda0b001cf25b9b968@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 7ae089234503..d7c4625583a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -17,10 +17,20 @@ #include "iwl-prph.h" #include "internal.h" +#define TRANS_CFG_MARKER BIT(0) +#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \ + struct _struct) +extern int _invalid_type; +#define _TRANS_CFG_MARKER(cfg) \ + (__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params), \ + TRANS_CFG_MARKER, \ + __builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type))) +#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg)) + #define IWL_PCI_DEVICE(dev, subdev, cfg) \ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ - .driver_data = (kernel_ulong_t)&(cfg) + .driver_data = _ASSIGN_CFG(cfg) /* Hardware specific file defines the PCI IDs table for that hardware module */ static const struct pci_device_id iwl_hw_card_ids[] = { @@ -1099,19 +1109,22 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - const struct iwl_cfg_trans_params *trans = - (struct iwl_cfg_trans_params *)(ent->driver_data); + const struct iwl_cfg_trans_params *trans; const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; struct iwl_trans *iwl_trans; struct iwl_trans_pcie *trans_pcie; int i, ret; + const struct iwl_cfg *cfg; + + trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER); + /* * This is needed for backwards compatibility with the old * tables, so we don't need to change all the config structs * at the same time. The cfg is used to compare with the old * full cfg structs. */ - const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); + cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER); /* make sure trans is the first element in iwl_cfg */ BUILD_BUG_ON(offsetof(struct iwl_cfg, trans)); @@ -1226,11 +1239,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #endif /* - * If we didn't set the cfg yet, assume the trans is actually - * a full cfg from the old tables. + * If we didn't set the cfg yet, the PCI ID table entry should have + * been a full config - if yes, use it, otherwise fail. */ - if (!iwl_trans->cfg) + if (!iwl_trans->cfg) { + if (ent->driver_data & TRANS_CFG_MARKER) { + pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n", + pdev->device, pdev->subsystem_device, + iwl_trans->hw_rev, iwl_trans->hw_rf_id); + ret = -EINVAL; + goto out_free_trans; + } iwl_trans->cfg = cfg; + } /* if we don't have a name yet, copy name from the old cfg */ if (!iwl_trans->name) From 9896b0b904455ef5371327e0fa8de823d192c5a1 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 30 Mar 2021 16:24:59 +0300 Subject: [PATCH 117/188] iwlwifi: mvm: support range request command version 12 Version 12 adds configuration of NDP ranging parameters: - max number of LTF repetitions - max number of spatial streams - max total LTFs Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.2c30c376c5cf.I01460f7277594ee7c98a8e1fe5447c59e70bf073@changeid Signed-off-by: Luca Coelho --- .../wireless/intel/iwlwifi/fw/api/location.h | 106 +++++++++++++++++- .../wireless/intel/iwlwifi/mvm/constants.h | 7 ++ .../intel/iwlwifi/mvm/ftm-initiator.c | 76 ++++++++++++- 3 files changed, 186 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index ceeef8749765..16af37f124ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -422,10 +422,12 @@ struct iwl_tof_range_req_ap_entry_v2 { * driver. * @IWL_INITIATOR_AP_FLAGS_NON_TB: Use non trigger based flow * @IWL_INITIATOR_AP_FLAGS_TB: Use trigger based flow - * @IWL_INITIATOR_AP_FLAGS_SECURED: request secured measurement + * @IWL_INITIATOR_AP_FLAGS_SECURED: request secure LTF measurement * @IWL_INITIATOR_AP_FLAGS_LMR_FEEDBACK: Send LMR feedback * @IWL_INITIATOR_AP_FLAGS_USE_CALIB: Use calibration values from the request * instead of fw internal values. + * @IWL_INITIATOR_AP_FLAGS_PMF: request to protect the negotiation and LMR + * frames with protected management frames. */ enum iwl_initiator_ap_flags { IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1), @@ -440,6 +442,7 @@ enum iwl_initiator_ap_flags { IWL_INITIATOR_AP_FLAGS_SECURED = BIT(11), IWL_INITIATOR_AP_FLAGS_LMR_FEEDBACK = BIT(12), IWL_INITIATOR_AP_FLAGS_USE_CALIB = BIT(13), + IWL_INITIATOR_AP_FLAGS_PMF = BIT(14), }; /** @@ -657,6 +660,79 @@ struct iwl_tof_range_req_ap_entry_v7 { u8 tx_pn[IEEE80211_CCMP_PN_LEN]; } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_7 */ +#define IWL_LOCATION_MAX_STS_POS 3 + +/** + * struct iwl_tof_range_req_ap_entry_v8 - AP configuration parameters + * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. + * @channel_num: AP Channel number + * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. + * bits 4 - 7: &enum iwl_location_bw. + * @ctrl_ch_position: Coding of the control channel position relative to the + * center frequency, see iwl_mvm_get_ctrl_pos(). + * @ftmr_max_retries: Max number of retries to send the FTMR in case of no + * reply from the AP. + * @bssid: AP's BSSID + * @burst_period: Recommended value to be sent to the AP. Measurement + * periodicity In units of 100ms. ignored if num_of_bursts_exp = 0 + * @samples_per_burst: the number of FTMs pairs in single Burst (1-31); + * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of + * the number of measurement iterations (min 2^0 = 1, max 2^14) + * @sta_id: the station id of the AP. Only relevant when associated to the AP, + * otherwise should be set to &IWL_MVM_INVALID_STA. + * @cipher: pairwise cipher suite for secured measurement. + * &enum iwl_location_cipher. + * @hltk: HLTK to be used for secured 11az measurement + * @tk: TK to be used for secured 11az measurement + * @calib: An array of calibration values per FTM rx bandwidth. + * If &IWL_INITIATOR_AP_FLAGS_USE_CALIB is set, the fw will use the + * calibration value that corresponds to the rx bandwidth of the FTM + * frame. + * @beacon_interval: beacon interval of the AP in TUs. Only required if + * &IWL_INITIATOR_AP_FLAGS_TB is set. + * @rx_pn: the next expected PN for protected management frames Rx. LE byte + * order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id + * is set to &IWL_MVM_INVALID_STA. + * @tx_pn: the next PN to use for protected management frames Tx. LE byte + * order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id + * is set to &IWL_MVM_INVALID_STA. + * @r2i_ndp_params: parameters for R2I NDP ranging negotiation. + * bits 0 - 2: max LTF repetitions + * bits 3 - 5: max number of spatial streams + * bits 6 - 7: reserved + * @i2r_ndp_params: parameters for I2R NDP ranging negotiation. + * bits 0 - 2: max LTF repetitions + * bits 3 - 5: max number of spatial streams (supported values are < 2) + * bits 6 - 7: reserved + * @r2i_max_total_ltf: R2I Max Total LTFs for NDP ranging negotiation. + * One of &enum ieee80211_range_params_max_total_ltf. + * @i2r_max_total_ltf: I2R Max Total LTFs for NDP ranging negotiation. + * One of &enum ieee80211_range_params_max_total_ltf. + */ +struct iwl_tof_range_req_ap_entry_v8 { + __le32 initiator_ap_flags; + u8 channel_num; + u8 format_bw; + u8 ctrl_ch_position; + u8 ftmr_max_retries; + u8 bssid[ETH_ALEN]; + __le16 burst_period; + u8 samples_per_burst; + u8 num_of_bursts; + u8 sta_id; + u8 cipher; + u8 hltk[HLTK_11AZ_LEN]; + u8 tk[TK_11AZ_LEN]; + __le16 calib[IWL_TOF_BW_NUM]; + __le16 beacon_interval; + u8 rx_pn[IEEE80211_CCMP_PN_LEN]; + u8 tx_pn[IEEE80211_CCMP_PN_LEN]; + u8 r2i_ndp_params; + u8 i2r_ndp_params; + u8 r2i_max_total_ltf; + u8 i2r_max_total_ltf; +} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_8 */ + /** * enum iwl_tof_response_mode * @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as @@ -878,6 +954,34 @@ struct iwl_tof_range_req_cmd_v11 { struct iwl_tof_range_req_ap_entry_v7 ap[IWL_MVM_TOF_MAX_APS]; } __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_11 */ +/** + * struct iwl_tof_range_req_cmd_v12 - start measurement cmd + * @initiator_flags: see flags @ iwl_tof_initiator_flags + * @request_id: A Token incremented per request. The same Token will be + * sent back in the range response + * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) + * @range_req_bssid: ranging request BSSID + * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. + * Bits set to 1 shall be randomized by the UMAC + * @macaddr_template: MAC address template to use for non-randomized bits + * @req_timeout_ms: Requested timeout of the response in units of milliseconds. + * This is the session time for completing the measurement. + * @tsf_mac_id: report the measurement start time for each ap in terms of the + * TSF of this mac id. 0xff to disable TSF reporting. + * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2. + */ +struct iwl_tof_range_req_cmd_v12 { + __le32 initiator_flags; + u8 request_id; + u8 num_of_ap; + u8 range_req_bssid[ETH_ALEN]; + u8 macaddr_mask[ETH_ALEN]; + u8 macaddr_template[ETH_ALEN]; + __le32 req_timeout_ms; + __le32 tsf_mac_id; + struct iwl_tof_range_req_ap_entry_v8 ap[IWL_MVM_TOF_MAX_APS]; +} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_12 */ + /* * enum iwl_tof_range_request_status - status of the sent request * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 617b41ee5801..2622debbb877 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -93,6 +93,13 @@ #define IWL_MVM_ENABLE_EBS 1 #define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE #define IWL_MVM_FTM_INITIATOR_DYNACK true +#define IWL_MVM_FTM_R2I_MAX_REP 7 +#define IWL_MVM_FTM_I2R_MAX_REP 7 +#define IWL_MVM_FTM_R2I_MAX_STS 1 +#define IWL_MVM_FTM_I2R_MAX_STS 1 +#define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF 3 +#define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF 3 +#define IWL_MVM_FTM_INITIATOR_SECURE_LTF false #define IWL_MVM_D3_DEBUG false #define IWL_MVM_USE_TWT true #define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index a4fd0bf9ba19..24ca2934bea0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -684,6 +684,19 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif, } } +static int +iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry_v7 *target) +{ + int err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target); + if (err) + return err; + + iwl_mvm_ftm_set_secured_ranging(mvm, vif, target); + return err; +} + static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_pmsr_request *req) @@ -704,11 +717,67 @@ static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm, struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; struct iwl_tof_range_req_ap_entry_v7 *target = &cmd.ap[i]; - err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target); + err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, target); + if (err) + return err; + } + + return iwl_mvm_ftm_send_cmd(mvm, &hcmd); +} + +static void +iwl_mvm_ftm_set_ndp_params(struct iwl_mvm *mvm, + struct iwl_tof_range_req_ap_entry_v8 *target) +{ + /* Only 2 STS are supported on Tx */ + u32 i2r_max_sts = IWL_MVM_FTM_I2R_MAX_STS > 1 ? 1 : + IWL_MVM_FTM_I2R_MAX_STS; + + target->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP | + (IWL_MVM_FTM_R2I_MAX_STS << IWL_LOCATION_MAX_STS_POS); + target->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP | + (i2r_max_sts << IWL_LOCATION_MAX_STS_POS); + target->r2i_max_total_ltf = IWL_MVM_FTM_R2I_MAX_TOTAL_LTF; + target->i2r_max_total_ltf = IWL_MVM_FTM_I2R_MAX_TOTAL_LTF; +} + +static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) +{ + struct iwl_tof_range_req_cmd_v12 cmd; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), + .dataflags[0] = IWL_HCMD_DFL_DUP, + .data[0] = &cmd, + .len[0] = sizeof(cmd), + }; + u8 i; + int err; + + iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req); + + for (i = 0; i < cmd.num_of_ap; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + struct iwl_tof_range_req_ap_entry_v8 *target = &cmd.ap[i]; + u32 flags; + + err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, (void *)target); if (err) return err; - iwl_mvm_ftm_set_secured_ranging(mvm, vif, target); + iwl_mvm_ftm_set_ndp_params(mvm, target); + + /* + * If secure LTF is turned off, replace the flag with PMF only + */ + flags = le32_to_cpu(target->initiator_ap_flags); + if ((flags & IWL_INITIATOR_AP_FLAGS_SECURED) && + !IWL_MVM_FTM_INITIATOR_SECURE_LTF) { + flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED; + flags |= IWL_INITIATOR_AP_FLAGS_PMF; + target->initiator_ap_flags = cpu_to_le32(flags); + } } return iwl_mvm_ftm_send_cmd(mvm, &hcmd); @@ -732,6 +801,9 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, IWL_FW_CMD_VER_UNKNOWN); switch (cmd_ver) { + case 12: + err = iwl_mvm_ftm_start_v12(mvm, vif, req); + break; case 11: err = iwl_mvm_ftm_start_v11(mvm, vif, req); break; From 20578872d503d5c211bdf334185ccd8afe4ae697 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 30 Mar 2021 16:25:00 +0300 Subject: [PATCH 118/188] iwlwifi: mvm: responder: support responder config command version 8 Version 8 add NDP ranging parameters configuration, as well as enable/disable NDP ranging and LMR feedback. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210330162204.ce9570d755d3.Ic81cb8da9aecbbc9edff468cb4ffbb741418cc73@changeid Signed-off-by: Luca Coelho --- .../wireless/intel/iwlwifi/fw/api/location.h | 67 ++++++++++++++++++- .../wireless/intel/iwlwifi/mvm/constants.h | 2 + .../intel/iwlwifi/mvm/ftm-responder.c | 27 +++++++- 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 16af37f124ee..0e38eb1cd75d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -147,6 +147,10 @@ enum iwl_tof_mcsi_enable { * @IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL: retry on algorithm failure * is valid * @IWL_TOF_RESPONDER_CMD_VALID_STA_ID: station ID is valid + * @IWL_TOF_RESPONDER_CMD_VALID_NDP_SUPPORT: enable/disable NDP ranging support + * is valid + * @IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS: NDP parameters are valid + * @IWL_TOF_RESPONDER_CMD_VALID_LMR_FEEDBACK: LMR feedback support is valid */ enum iwl_tof_responder_cmd_valid_field { IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO = BIT(0), @@ -162,6 +166,9 @@ enum iwl_tof_responder_cmd_valid_field { IWL_TOF_RESPONDER_CMD_VALID_FAST_ALGO_SUPPORT = BIT(10), IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL = BIT(11), IWL_TOF_RESPONDER_CMD_VALID_STA_ID = BIT(12), + IWL_TOF_RESPONDER_CMD_VALID_NDP_SUPPORT = BIT(22), + IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS = BIT(23), + IWL_TOF_RESPONDER_CMD_VALID_LMR_FEEDBACK = BIT(24), }; /** @@ -176,6 +183,9 @@ enum iwl_tof_responder_cmd_valid_field { * @IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT: fast algorithm support * @IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL: retry on algorithm fail * @IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT: TX antenna mask + * @IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT: support NDP ranging + * @IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK: request for LMR feedback if the + * initiator supports it */ enum iwl_tof_responder_cfg_flags { IWL_TOF_RESPONDER_FLAGS_NON_ASAP_SUPPORT = BIT(0), @@ -188,6 +198,8 @@ enum iwl_tof_responder_cfg_flags { IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9), IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10), IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK, + IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT = BIT(24), + IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK = BIT(25), }; /** @@ -226,7 +238,7 @@ struct iwl_tof_responder_config_cmd_v6 { } __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */ /** - * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug) + * struct iwl_tof_responder_config_cmd_v7 - ToF AP mode (for debug) * @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field * @responder_cfg_flags: &iwl_tof_responder_cfg_flags * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. @@ -245,7 +257,7 @@ struct iwl_tof_responder_config_cmd_v6 { * @bssid: Current AP BSSID * @reserved2: reserved */ -struct iwl_tof_responder_config_cmd { +struct iwl_tof_responder_config_cmd_v7 { __le32 cmd_valid_fields; __le32 responder_cfg_flags; u8 format_bw; @@ -259,7 +271,56 @@ struct iwl_tof_responder_config_cmd { __le16 specific_calib; u8 bssid[ETH_ALEN]; __le16 reserved2; -} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */ +} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_7 */ + +#define IWL_RESPONDER_STS_POS 3 +#define IWL_RESPONDER_TOTAL_LTF_POS 6 + +/** + * struct iwl_tof_responder_config_cmd_v8 - ToF AP mode (for debug) + * @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field + * @responder_cfg_flags: &iwl_tof_responder_cfg_flags + * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. + * bits 4 - 7: &enum iwl_location_bw. + * @rate: current AP rate + * @channel_num: current AP Channel + * @ctrl_ch_position: coding of the control channel position relative to + * the center frequency, see iwl_mvm_get_ctrl_pos() + * @sta_id: index of the AP STA when in AP mode + * @reserved1: reserved + * @toa_offset: Artificial addition [pSec] for the ToA - to be used for debug + * purposes, simulating station movement by adding various values + * to this field + * @common_calib: XVT: common calibration value + * @specific_calib: XVT: specific calibration value + * @bssid: Current AP BSSID + * @r2i_ndp_params: parameters for R2I NDP. + * bits 0 - 2: max number of LTF repetitions + * bits 3 - 5: max number of spatial streams (supported values are < 2) + * bits 6 - 7: max number of total LTFs + * (&enum ieee80211_range_params_max_total_ltf) + * @i2r_ndp_params: parameters for I2R NDP. + * bits 0 - 2: max number of LTF repetitions + * bits 3 - 5: max number of spatial streams + * bits 6 - 7: max number of total LTFs + * (&enum ieee80211_range_params_max_total_ltf) + */ +struct iwl_tof_responder_config_cmd_v8 { + __le32 cmd_valid_fields; + __le32 responder_cfg_flags; + u8 format_bw; + u8 rate; + u8 channel_num; + u8 ctrl_ch_position; + u8 sta_id; + u8 reserved1; + __le16 toa_offset; + __le16 common_calib; + __le16 specific_calib; + u8 bssid[ETH_ALEN]; + u8 r2i_ndp_params; + u8 i2r_ndp_params; +} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_8 */ #define IWL_LCI_CIVIC_IE_MAX_SIZE 400 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 2622debbb877..45634302801f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -100,6 +100,8 @@ #define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF 3 #define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF 3 #define IWL_MVM_FTM_INITIATOR_SECURE_LTF false +#define IWL_MVM_FTM_RESP_NDP_SUPPORT true +#define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT true #define IWL_MVM_D3_DEBUG false #define IWL_MVM_USE_TWT true #define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c index 996f45c19f10..5a249ea97eb2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -75,6 +75,24 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef, return 0; } +static void +iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm, + struct iwl_tof_responder_config_cmd_v8 *cmd) +{ + /* Up to 2 R2I STS are allowed on the responder */ + u32 r2i_max_sts = IWL_MVM_FTM_R2I_MAX_STS < 2 ? + IWL_MVM_FTM_R2I_MAX_STS : 1; + + cmd->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP | + (r2i_max_sts << IWL_RESPONDER_STS_POS) | + (IWL_MVM_FTM_R2I_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS); + cmd->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP | + (IWL_MVM_FTM_I2R_MAX_STS << IWL_RESPONDER_STS_POS) | + (IWL_MVM_FTM_I2R_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS); + cmd->cmd_valid_fields |= + cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS); +} + static int iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -82,11 +100,11 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); /* - * The command structure is the same for versions 6 and 7, (only the + * The command structure is the same for versions 6, 7 and 8 (only the * field interpretation is different), so the same struct can be use * for all cases. */ - struct iwl_tof_responder_config_cmd cmd = { + struct iwl_tof_responder_config_cmd_v8 cmd = { .channel_num = chandef->chan->hw_value, .cmd_valid_fields = cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO | @@ -100,7 +118,10 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, lockdep_assert_held(&mvm->mutex); - if (cmd_ver == 7) +if (cmd_ver == 8) + iwl_mvm_ftm_responder_set_ndp(mvm, &cmd); + + if (cmd_ver >= 7) err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw, &cmd.ctrl_ch_position); else From 5f8a3561ea8bf75ad52cb16dafe69dd550fa542e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Mar 2021 12:14:41 +0300 Subject: [PATCH 119/188] iwlwifi: mvm: write queue_sync_state only for sync We use mvm->queue_sync_state to wait for synchronous queue sync messages, but if an async one happens inbetween we shouldn't clear mvm->queue_sync_state after sending the async one, that can run concurrently (at least from the CPU POV) with another synchronous queue sync. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.d11c9bcdb4aa.I0772171dbaec87433a11513e9586d98b5d920b5f@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 9ed6e2783cc4..fbd37a19b6e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -5177,9 +5177,10 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, } out: - mvm->queue_sync_state = 0; - if (notif->sync) + if (notif->sync) { + mvm->queue_sync_state = 0; mvm->queue_sync_cookie++; + } } static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) From 5e1688ce914d46f37cce4695f6aebb1ecb9943e0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Mar 2021 12:14:42 +0300 Subject: [PATCH 120/188] iwlwifi: mvm: clean up queue sync implementation When we do queue sync, it's confusing that we have the structures declared in the FW API header files that aren't really firmware, and the union is also confusing - especially now in the code that checks the size on the return. So rework this: change the type of sync and whether to do it in a synchronous fashion to arguments, and build the data structure in the function, so we don't need the union. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.f62833fd9893.I612d7ac1c655ec4880329360e15d207698c750bc@changeid Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/rx.h | 30 ---------- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 44 +++++++++----- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 8 +-- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 58 ++++--------------- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 ++-- drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 38 +++++++++--- 6 files changed, 80 insertions(+), 108 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 2c74db823778..3f13b572915a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -779,36 +779,6 @@ struct iwl_rxq_sync_notification { u8 payload[]; } __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */ -/** - * enum iwl_mvm_rxq_notif_type - Internal message identifier - * - * @IWL_MVM_RXQ_EMPTY: empty sync notification - * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA - * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN - */ -enum iwl_mvm_rxq_notif_type { - IWL_MVM_RXQ_EMPTY, - IWL_MVM_RXQ_NOTIF_DEL_BA, - IWL_MVM_RXQ_NSSN_SYNC, -}; - -/** - * struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent - * in &iwl_rxq_sync_cmd. Should be DWORD aligned. - * FW is agnostic to the payload, so there are no endianity requirements. - * - * @type: value from &iwl_mvm_rxq_notif_type - * @sync: ctrl path is waiting for all notifications to be received - * @cookie: internal cookie to identify old notifications - * @data: payload - */ -struct iwl_mvm_internal_rxq_notif { - u16 type; - u16 sync; - u32 cookie; - u8 data[]; -} __packed; - /** * enum iwl_mvm_pm_event - type of station PM event * @IWL_MVM_PM_EVENT_AWAKE: station woke up diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index fbd37a19b6e0..fd35dd31613e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -5144,28 +5144,50 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, } void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, - struct iwl_mvm_internal_rxq_notif *notif, - u32 size) + enum iwl_mvm_rxq_notif_type type, + bool sync, + const void *data, u32 size) { - u32 qmask = BIT(mvm->trans->num_rx_queues) - 1; + struct { + struct iwl_rxq_sync_cmd cmd; + struct iwl_mvm_internal_rxq_notif notif; + } __packed cmd = { + .cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1), + .cmd.count = + cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) + + size), + .notif.type = type, + .notif.sync = sync, + }; + struct iwl_host_cmd hcmd = { + .id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD), + .data[0] = &cmd, + .len[0] = sizeof(cmd), + .data[1] = data, + .len[1] = size, + .flags = sync ? 0 : CMD_ASYNC, + }; int ret; + /* size must be a multiple of DWORD */ + if (WARN_ON(cmd.cmd.count & cpu_to_le32(3))) + return; if (!iwl_mvm_has_new_rx_api(mvm)) return; - if (notif->sync) { - notif->cookie = mvm->queue_sync_cookie; + if (sync) { + cmd.notif.cookie = mvm->queue_sync_cookie; mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1; } - ret = iwl_mvm_notify_rx_queue(mvm, qmask, notif, size, !notif->sync); + ret = iwl_mvm_send_cmd(mvm, &hcmd); if (ret) { IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret); goto out; } - if (notif->sync) { + if (sync) { lockdep_assert_held(&mvm->mutex); ret = wait_event_timeout(mvm->rx_sync_waitq, READ_ONCE(mvm->queue_sync_state) == 0 || @@ -5177,7 +5199,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, } out: - if (notif->sync) { + if (sync) { mvm->queue_sync_state = 0; mvm->queue_sync_cookie++; } @@ -5186,13 +5208,9 @@ out: static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_internal_rxq_notif data = { - .type = IWL_MVM_RXQ_EMPTY, - .sync = 1, - }; mutex_lock(&mvm->mutex); - iwl_mvm_sync_rx_queues_internal(mvm, &data, sizeof(data)); + iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY, true, NULL, 0); mutex_unlock(&mvm->mutex); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 0a963d01b825..e607ad713f88 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1570,9 +1570,6 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue); void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue); -int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, - const struct iwl_mvm_internal_rxq_notif *notif, - u32 notif_size, bool async); void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue); void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); @@ -2001,8 +1998,9 @@ void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_tdls_ch_switch_work(struct work_struct *work); void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, - struct iwl_mvm_internal_rxq_notif *notif, - u32 size); + enum iwl_mvm_rxq_notif_type type, + bool sync, + const void *data, u32 size); void iwl_mvm_reorder_timer_expired(struct timer_list *t); struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index af5a6dd81c41..8e26422ca326 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -527,37 +527,6 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue, return false; } -int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, - const struct iwl_mvm_internal_rxq_notif *notif, - u32 notif_size, bool async) -{ - u8 buf[sizeof(struct iwl_rxq_sync_cmd) + - sizeof(struct iwl_mvm_rss_sync_notif)]; - struct iwl_rxq_sync_cmd *cmd = (void *)buf; - u32 data_size = sizeof(*cmd) + notif_size; - int ret; - - /* - * size must be a multiple of DWORD - * Ensure we don't overflow buf - */ - if (WARN_ON(notif_size & 3 || - notif_size > sizeof(struct iwl_mvm_rss_sync_notif))) - return -EINVAL; - - cmd->rxq_mask = cpu_to_le32(rxq_mask); - cmd->count = cpu_to_le32(notif_size); - cmd->flags = 0; - memcpy(cmd->payload, notif, notif_size); - - ret = iwl_mvm_send_cmd_pdu(mvm, - WIDE_ID(DATA_PATH_GROUP, - TRIGGER_RX_QUEUES_NOTIF_CMD), - async ? CMD_ASYNC : 0, data_size, cmd); - - return ret; -} - /* * Returns true if sn2 - buffer_size < sn1 < sn2. * To be used only in order to compare reorder buffer head with NSSN. @@ -573,15 +542,13 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size) static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn) { if (IWL_MVM_USE_NSSN_SYNC) { - struct iwl_mvm_rss_sync_notif notif = { - .metadata.type = IWL_MVM_RXQ_NSSN_SYNC, - .metadata.sync = 0, - .nssn_sync.baid = baid, - .nssn_sync.nssn = nssn, + struct iwl_mvm_nssn_sync_data notif = { + .baid = baid, + .nssn = nssn, }; - iwl_mvm_sync_rx_queues_internal(mvm, (void *)¬if, - sizeof(notif)); + iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NSSN_SYNC, false, + ¬if, sizeof(notif)); } } @@ -830,8 +797,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi, "invalid notification size %d (%d)", len, (int)(sizeof(*notif) + sizeof(*internal_notif)))) return; - /* remove only the firmware header, we want all of our payload below */ - len -= sizeof(*notif); + len -= sizeof(*notif) + sizeof(*internal_notif); if (internal_notif->sync && mvm->queue_sync_cookie != internal_notif->cookie) { @@ -841,21 +807,19 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi, switch (internal_notif->type) { case IWL_MVM_RXQ_EMPTY: - WARN_ONCE(len != sizeof(*internal_notif), - "invalid empty notification size %d (%d)", - len, (int)sizeof(*internal_notif)); + WARN_ONCE(len, "invalid empty notification size %d", len); break; case IWL_MVM_RXQ_NOTIF_DEL_BA: - if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif), + if (WARN_ONCE(len != sizeof(struct iwl_mvm_delba_data), "invalid delba notification size %d (%d)", - len, (int)sizeof(struct iwl_mvm_rss_sync_notif))) + len, (int)sizeof(struct iwl_mvm_delba_data))) break; iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data); break; case IWL_MVM_RXQ_NSSN_SYNC: - if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif), + if (WARN_ONCE(len != sizeof(struct iwl_mvm_nssn_sync_data), "invalid nssn sync notification size %d (%d)", - len, (int)sizeof(struct iwl_mvm_rss_sync_notif))) + len, (int)sizeof(struct iwl_mvm_nssn_sync_data))) break; iwl_mvm_nssn_sync(mvm, napi, queue, (void *)internal_notif->data); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 3a411bbda5fd..f618368eda83 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2441,12 +2441,12 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid) { - struct iwl_mvm_rss_sync_notif notif = { - .metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA, - .metadata.sync = 1, - .delba.baid = baid, + struct iwl_mvm_delba_data notif = { + .baid = baid, }; - iwl_mvm_sync_rx_queues_internal(mvm, (void *)¬if, sizeof(notif)); + + iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NOTIF_DEL_BA, true, + ¬if, sizeof(notif)); }; static void iwl_mvm_free_reorder(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 35a18b96aac5..32b4d1935788 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -281,6 +281,36 @@ struct iwl_mvm_key_pn { } ____cacheline_aligned_in_smp q[]; }; +/** + * enum iwl_mvm_rxq_notif_type - Internal message identifier + * + * @IWL_MVM_RXQ_EMPTY: empty sync notification + * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA + * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN + */ +enum iwl_mvm_rxq_notif_type { + IWL_MVM_RXQ_EMPTY, + IWL_MVM_RXQ_NOTIF_DEL_BA, + IWL_MVM_RXQ_NSSN_SYNC, +}; + +/** + * struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent + * in &iwl_rxq_sync_cmd. Should be DWORD aligned. + * FW is agnostic to the payload, so there are no endianity requirements. + * + * @type: value from &iwl_mvm_rxq_notif_type + * @sync: ctrl path is waiting for all notifications to be received + * @cookie: internal cookie to identify old notifications + * @data: payload + */ +struct iwl_mvm_internal_rxq_notif { + u16 type; + u16 sync; + u32 cookie; + u8 data[]; +} __packed; + struct iwl_mvm_delba_data { u32 baid; } __packed; @@ -290,14 +320,6 @@ struct iwl_mvm_nssn_sync_data { u32 nssn; } __packed; -struct iwl_mvm_rss_sync_notif { - struct iwl_mvm_internal_rxq_notif metadata; - union { - struct iwl_mvm_delba_data delba; - struct iwl_mvm_nssn_sync_data nssn_sync; - }; -} __packed; - /** * struct iwl_mvm_rxq_dup_data - per station per rx queue data * @last_seq: last sequence per tid for duplicate packet detection From 517a5eb9fab2bf1d078ee0d3f95abf6a7aa092f8 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Wed, 31 Mar 2021 12:14:43 +0300 Subject: [PATCH 121/188] iwlwifi: mvm: when associated with PMF, use protected NDP ranging negotiation When associated to the resonder with PMF, request to protect the NDP ranging negotiation with PMF. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.e7982c72e12b.Ib6db362d01a31132c638e194d49476cd8e3ff430@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 24ca2934bea0..a456b8a0ae58 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -490,6 +490,15 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (vif->bss_conf.assoc && !memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct ieee80211_sta *sta; + + rcu_read_lock(); + + sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]); + if (sta->mfp) + FTM_PUT_FLAG(PMF); + + rcu_read_unlock(); target->sta_id = mvmvif->ap_sta_id; } else { From 85b5fd94d7d9d7e775024cd0ba0f31c432bea79b Mon Sep 17 00:00:00 2001 From: ybaruch Date: Wed, 31 Mar 2021 12:14:44 +0300 Subject: [PATCH 122/188] iwlwifi: add ax201 killer device add new killer devices configurations. Signed-off-by: ybaruch Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.54967363d26d.I5d1a3d810cf6abace51ebb2630d62d891e9fd302@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 4 ++++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index bea3d5f3014a..d775cd9c1394 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -399,6 +399,10 @@ const char iwl_ax201_killer_1650s_name[] = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)"; const char iwl_ax201_killer_1650i_name[] = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)"; +const char iwl_ax210_killer_1675w_name[] = + "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)"; +const char iwl_ax210_killer_1675x_name[] = + "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)"; const struct iwl_cfg iwl_qu_b0_hr1_b0 = { .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index f041f7f2160b..bdf352e97f51 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -503,6 +503,8 @@ extern const char iwl_ax200_killer_1650w_name[]; extern const char iwl_ax200_killer_1650x_name[]; extern const char iwl_ax201_killer_1650s_name[]; extern const char iwl_ax201_killer_1650i_name[]; +extern const char iwl_ax210_killer_1675w_name[]; +extern const char iwl_ax210_killer_1675x_name[]; extern const char iwl_ma_name[]; extern const char iwl_ax211_name[]; extern const char iwl_ax411_name[]; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index d7c4625583a8..dd7e295397c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -619,6 +619,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x2725, 0x4020, iwlax210_2ax_cfg_ty_gf_a0, NULL), IWL_DEV_INFO(0x2725, 0x6020, iwlax210_2ax_cfg_ty_gf_a0, NULL), IWL_DEV_INFO(0x2725, 0x6024, iwlax210_2ax_cfg_ty_gf_a0, NULL), + IWL_DEV_INFO(0x2725, 0x1673, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675w_name), + IWL_DEV_INFO(0x2725, 0x1674, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675x_name), IWL_DEV_INFO(0x7A70, 0x0090, iwlax211_2ax_cfg_so_gf_a0_long, NULL), IWL_DEV_INFO(0x7A70, 0x0098, iwlax211_2ax_cfg_so_gf_a0_long, NULL), IWL_DEV_INFO(0x7A70, 0x00B0, iwlax411_2ax_cfg_so_gf4_a0_long, NULL), From e8fe3b41c3a36c7a7aa88bdfec112b91530577e4 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 31 Mar 2021 12:14:46 +0300 Subject: [PATCH 123/188] iwlwifi: mvm: Add support for 6GHz passive scan When doing scan while 6GHz channels are not enabled, the 6GHz band is not scanned. Thus, if there are no APs on the 2GHz and 5GHz bands (that will allow discovery of geographic location etc. that would allow enabling the 6GHz channels) but there are non collocated APs on 6GHz PSC channels these would never be discovered. To overcome this, FW added support for performing passive UHB scan in case no APs were discovered during scan on the 2GHz and 5GHz channels. Add support for enabling such scan when the following conditions are met: - 6GHz channels are supported but not enabled by regulatory. - Station interface is not associated or less than a defined time interval passed from the last resume or HW reset flows. - At least 4 channels are included in the scan request - The scan request includes the widlcard SSID. - At least 50 minutes passed from the last 6GHz passive scan. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.7c7bd00e0aeb.Ib226ad57e416b43a710c36a78a617d4243458b99@changeid Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/scan.h | 8 ++ drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 + .../wireless/intel/iwlwifi/mvm/constants.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 2 + .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 + drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 128 ++++++++++++++++++ 7 files changed, 148 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 6b8ca35cec1a..b2605aefc290 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -634,6 +634,12 @@ enum iwl_umac_scan_general_flags2 { * @IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN: at the end of 2.4GHz and * 5.2Ghz bands scan, trigger scan on 6GHz band to discover * the reported collocated APs + * @IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN: at the end of 2.4GHz and 5GHz + * bands scan, if not APs were discovered, allow scan to conitnue and scan + * 6GHz PSC channels in order to discover country information. + * @IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN_FILTER_IN: in case + * &IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN is enabled and scan is + * activated over 6GHz PSC channels, filter in beacons and probe responses. */ enum iwl_umac_scan_general_flags_v2 { IWL_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC = BIT(0), @@ -649,6 +655,8 @@ enum iwl_umac_scan_general_flags_v2 { IWL_UMAC_SCAN_GEN_FLAGS_V2_MULTI_SSID = BIT(10), IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE = BIT(11), IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN = BIT(12), + IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN = BIT(13), + IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN_FILTER_IN = BIT(14), }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 35dffcaf5aba..f9c5cf538ad1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -362,6 +362,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_PROTECTED_TWT: Supports protection of TWT action frames * @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in * reset flow + * @IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN: Support for passive scan on 6GHz PSC + * channels even when these are not enabled. * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -408,6 +410,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD = (__force iwl_ucode_tlv_capa_t)54, IWL_UCODE_TLV_CAPA_PROTECTED_TWT = (__force iwl_ucode_tlv_capa_t)56, IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE = (__force iwl_ucode_tlv_capa_t)57, + IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)58, /* set 2 */ IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 45634302801f..1343f25f1090 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -117,5 +117,7 @@ #define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016 #define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2 #define IWL_MVM_DISABLE_AP_FILS false +#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */ +#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */ #endif /* __MVM_CONSTANTS_H */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index a7dc85c704a9..2e28cf299ef4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2028,6 +2028,8 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) mutex_lock(&mvm->mutex); + mvm->last_reset_or_resume_time_jiffies = jiffies; + /* get the BSS vif pointer again */ vif = iwl_mvm_get_bss_vif(mvm); if (IS_ERR_OR_NULL(vif)) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index fd35dd31613e..607d5d564928 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1099,6 +1099,8 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm) iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC, NULL); + mvm->last_reset_or_resume_time_jiffies = jiffies; + if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { /* Something went wrong - we need to finish some cleanup * that normally iwl_mvm_mac_restart_complete() below diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index e607ad713f88..e2a37ac7c4b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1096,6 +1096,9 @@ struct iwl_mvm { /* sniffer data to include in radiotap */ __le16 cur_aid; u8 cur_bssid[ETH_ALEN]; + + unsigned long last_6ghz_passive_scan_jiffies; + unsigned long last_reset_or_resume_time_jiffies; }; /* Extract MVM priv from op_mode and _hw */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index caf87f320094..5a0696c44f6d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -43,6 +43,9 @@ /* adaptive dwell number of APs override for social channels */ #define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS 2 +/* minimal number of 2GHz and 5GHz channels in the regular scan request */ +#define IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS 4 + struct iwl_mvm_scan_timing_params { u32 suspend_time; u32 max_out_time; @@ -94,6 +97,7 @@ struct iwl_mvm_scan_params { struct cfg80211_scan_6ghz_params *scan_6ghz_params; u32 n_6ghz_params; bool scan_6ghz; + bool enable_6ghz_passive; }; static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm) @@ -1873,6 +1877,98 @@ static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm, return flags; } +static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm, + struct iwl_mvm_scan_params *params, + struct ieee80211_vif *vif) +{ + struct ieee80211_supported_band *sband = + &mvm->nvm_data->bands[NL80211_BAND_6GHZ]; + u32 n_disabled, i; + + params->enable_6ghz_passive = false; + + if (params->scan_6ghz) + return; + + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN)) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: Not supported by FW\n"); + return; + } + + /* 6GHz passive scan allowed only on station interface */ + if (vif->type != NL80211_IFTYPE_STATION) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: not station interface\n"); + return; + } + + /* + * 6GHz passive scan is allowed while associated in a defined time + * interval following HW reset or resume flow + */ + if (vif->bss_conf.assoc && + (time_before(mvm->last_reset_or_resume_time_jiffies + + (IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT * HZ), + jiffies))) { + IWL_DEBUG_SCAN(mvm, "6GHz passive scan: associated\n"); + return; + } + + /* No need for 6GHz passive scan if not enough time elapsed */ + if (time_after(mvm->last_6ghz_passive_scan_jiffies + + (IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT * HZ), jiffies)) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: timeout did not expire\n"); + return; + } + + /* not enough channels in the regular scan request */ + if (params->n_channels < IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: not enough channels\n"); + return; + } + + for (i = 0; i < params->n_ssids; i++) { + if (!params->ssids[i].ssid_len) + break; + } + + /* not a wildcard scan, so cannot enable passive 6GHz scan */ + if (i == params->n_ssids) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: no wildcard SSID\n"); + return; + } + + if (!sband || !sband->n_channels) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: no 6GHz channels\n"); + return; + } + + for (i = 0, n_disabled = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED)) + n_disabled++; + } + + /* + * Not all the 6GHz channels are disabled, so no need for 6GHz passive + * scan + */ + if (n_disabled != sband->n_channels) { + IWL_DEBUG_SCAN(mvm, + "6GHz passive scan: 6GHz channels enabled\n"); + return; + } + + /* all conditions to enable 6ghz passive scan are satisfied */ + IWL_DEBUG_SCAN(mvm, "6GHz passive scan: can be enabled\n"); + params->enable_6ghz_passive = true; +} + static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, struct ieee80211_vif *vif, @@ -1911,6 +2007,9 @@ static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm, params->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ) flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN; + if (params->enable_6ghz_passive) + flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN; + return flags; } @@ -2183,6 +2282,30 @@ iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm, params->n_channels, channel_cfg_flags, vif->type); + + if (params->enable_6ghz_passive) { + struct ieee80211_supported_band *sband = + &mvm->nvm_data->bands[NL80211_BAND_6GHZ]; + u32 i; + + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *channel = + &sband->channels[i]; + + struct iwl_scan_channel_cfg_umac *cfg = + &cp->channel_config[cp->count]; + + if (!cfg80211_channel_is_psc(channel)) + continue; + + cfg->flags = 0; + cfg->v2.channel_num = channel->hw_value; + cfg->v2.band = PHY_BAND_6; + cfg->v2.iter_count = 1; + cfg->v2.iter_interval = 0; + cp->count++; + } + } } static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -2500,6 +2623,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms); + iwl_mvm_scan_6ghz_passive_scan(mvm, ¶ms, vif); + uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, ¶ms, IWL_MVM_SCAN_REGULAR); @@ -2524,6 +2649,9 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvm->scan_status |= IWL_MVM_SCAN_REGULAR; mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif); + if (params.enable_6ghz_passive) + mvm->last_6ghz_passive_scan_jiffies = jiffies; + schedule_delayed_work(&mvm->scan_timeout_dwork, msecs_to_jiffies(SCAN_TIMEOUT)); From e12cfc7bbfd31c1be6567b296ea058e35fba91ab Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 31 Mar 2021 12:14:47 +0300 Subject: [PATCH 124/188] iwlwifi: mvm: enable PPAG in China Add support for ppag in China by reading revision 2 of the ppag table from ACPI, and passing the data to the FW. This is needed to enable OEMs to control ppag enablement in China. Signed-off-by: Miri Korenblit Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.69af388d0dce.I8cfddf9e6837bf394b00390181b4b774ded19acd@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 9 +-- drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 4 +- .../net/wireless/intel/iwlwifi/fw/api/power.h | 22 +++--- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 76 ++++++++++++------- 4 files changed, 65 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 82a4f7e8ba54..56c4d05c9cc2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -181,14 +181,13 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev, /* * We need at least two packages, one for the revision and one * for the data itself. Also check that the revision is valid - * (i.e. it is an integer smaller than 2, as we currently support only - * 2 revisions). + * (i.e. it is an integer (each caller has to check by itself + * if the returned revision is supported)). */ if (data->type != ACPI_TYPE_PACKAGE || data->package.count < 2 || - data->package.elements[0].type != ACPI_TYPE_INTEGER || - data->package.elements[0].integer.value > 1) { - IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n"); + data->package.elements[0].type != ACPI_TYPE_INTEGER) { + IWL_DEBUG_DEV_RADIO(dev, "Invalid packages structure\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 030c50082568..f8ea588e4fbb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -53,8 +53,8 @@ #define ACPI_WGDS_TABLE_SIZE 3 -#define ACPI_PPAG_WIFI_DATA_SIZE ((IWL_NUM_CHAIN_LIMITS * \ - IWL_NUM_SUB_BANDS) + 2) +#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \ + IWL_NUM_SUB_BANDS_V1) + 2) #define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \ IWL_NUM_SUB_BANDS_V2) + 2) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 798417182d54..86445385f072 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -274,7 +274,7 @@ enum iwl_dev_tx_power_cmd_mode { #define IWL_NUM_CHAIN_TABLES 1 #define IWL_NUM_CHAIN_TABLES_V2 2 #define IWL_NUM_CHAIN_LIMITS 2 -#define IWL_NUM_SUB_BANDS 5 +#define IWL_NUM_SUB_BANDS_V1 5 #define IWL_NUM_SUB_BANDS_V2 11 /** @@ -300,7 +300,7 @@ struct iwl_dev_tx_power_common { * @per_chain: per chain restrictions */ struct iwl_dev_tx_power_cmd_v3 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS]; + __le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1]; } __packed; /* TX_REDUCED_POWER_API_S_VER_3 */ #define IWL_DEV_MAX_TX_POWER 0x7FFF @@ -313,7 +313,7 @@ struct iwl_dev_tx_power_cmd_v3 { * @reserved: reserved (padding) */ struct iwl_dev_tx_power_cmd_v4 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS]; + __le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1]; u8 enable_ack_reduction; u8 reserved[3]; } __packed; /* TX_REDUCED_POWER_API_S_VER_4 */ @@ -332,7 +332,7 @@ struct iwl_dev_tx_power_cmd_v4 { * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER */ struct iwl_dev_tx_power_cmd_v5 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS]; + __le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1]; u8 enable_ack_reduction; u8 per_chain_restriction_changed; u8 reserved[2]; @@ -454,21 +454,23 @@ struct iwl_geo_tx_power_profiles_resp { /** * union iwl_ppag_table_cmd - union for all versions of PPAG command - * @v1: version 1, table revision = 0 - * @v2: version 2, table revision = 1 + * @v1: version 1 + * @v2: version 2 * - * @enabled: 1 if PPAG is enabled, 0 otherwise + * @flags: bit 0 - indicates enablement of PPAG for ETSI + * bit 1 - indicates enablement of PPAG for CHINA BIOS + * bit 1 can be used only in v3 (identical to v2) * @gain: table of antenna gain values per chain and sub-band * @reserved: reserved */ union iwl_ppag_table_cmd { struct { - __le32 enabled; - s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS]; + __le32 flags; + s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1]; s8 reserved[2]; } v1; struct { - __le32 enabled; + __le32 flags; s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; s8 reserved[2]; } v2; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 5ee64f7f3c85..4f297edd8e18 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -29,6 +29,9 @@ #define UCODE_VALID_OK cpu_to_le32(0x1) +#define IWL_PPAG_MASK 3 +#define IWL_PPAG_ETSI_MASK BIT(0) + struct iwl_mvm_alive_data { bool valid; u32 scd_base_addr; @@ -773,16 +776,16 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) } else if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_REDUCE_TX_POWER)) { len = sizeof(cmd.v5); - n_subbands = IWL_NUM_SUB_BANDS; + n_subbands = IWL_NUM_SUB_BANDS_V1; per_chain = cmd.v5.per_chain[0][0]; } else if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TX_POWER_ACK)) { len = sizeof(cmd.v4); - n_subbands = IWL_NUM_SUB_BANDS; + n_subbands = IWL_NUM_SUB_BANDS_V1; per_chain = cmd.v4.per_chain[0][0]; } else { len = sizeof(cmd.v3); - n_subbands = IWL_NUM_SUB_BANDS; + n_subbands = IWL_NUM_SUB_BANDS_V1; per_chain = cmd.v3.per_chain[0][0]; } @@ -909,46 +912,50 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) { - union acpi_object *wifi_pkg, *data, *enabled; + union acpi_object *wifi_pkg, *data, *flags; int i, j, ret, tbl_rev, num_sub_bands; int idx = 2; s8 *gain; /* - * The 'enabled' field is the same in v1 and v2 so we can just + * The 'flags' field is the same in v1 and in v2 so we can just * use v1 to access it. */ - mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0); + mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0); + data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD); if (IS_ERR(data)) return PTR_ERR(data); - /* try to read ppag table revision 1 */ + /* try to read ppag table rev 2 or 1 (both have the same data size) */ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev); if (!IS_ERR(wifi_pkg)) { - if (tbl_rev != 1) { + if (tbl_rev == 1 || tbl_rev == 2) { + num_sub_bands = IWL_NUM_SUB_BANDS_V2; + gain = mvm->fwrt.ppag_table.v2.gain[0]; + mvm->fwrt.ppag_ver = tbl_rev; + IWL_DEBUG_RADIO(mvm, + "Reading PPAG table v2 (tbl_rev=%d)\n", + tbl_rev); + goto read_table; + } else { ret = -EINVAL; goto out_free; } - num_sub_bands = IWL_NUM_SUB_BANDS_V2; - gain = mvm->fwrt.ppag_table.v2.gain[0]; - mvm->fwrt.ppag_ver = 2; - IWL_DEBUG_RADIO(mvm, "Reading PPAG table v2 (tbl_rev=1)\n"); - goto read_table; } /* try to read ppag table revision 0 */ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, - ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev); + ACPI_PPAG_WIFI_DATA_SIZE_V1, &tbl_rev); if (!IS_ERR(wifi_pkg)) { if (tbl_rev != 0) { ret = -EINVAL; goto out_free; } - num_sub_bands = IWL_NUM_SUB_BANDS; + num_sub_bands = IWL_NUM_SUB_BANDS_V1; gain = mvm->fwrt.ppag_table.v1.gain[0]; - mvm->fwrt.ppag_ver = 1; + mvm->fwrt.ppag_ver = 0; IWL_DEBUG_RADIO(mvm, "Reading PPAG table v1 (tbl_rev=0)\n"); goto read_table; } @@ -956,15 +963,17 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) goto out_free; read_table: - enabled = &wifi_pkg->package.elements[1]; - if (enabled->type != ACPI_TYPE_INTEGER || - (enabled->integer.value != 0 && enabled->integer.value != 1)) { + flags = &wifi_pkg->package.elements[1]; + + if (flags->type != ACPI_TYPE_INTEGER) { ret = -EINVAL; goto out_free; } - mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value); - if (!mvm->fwrt.ppag_table.v1.enabled) { + mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(flags->integer.value & + IWL_PPAG_MASK); + + if (!mvm->fwrt.ppag_table.v1.flags) { ret = 0; goto out_free; } @@ -992,12 +1001,13 @@ read_table: (j != 0 && (gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_HB || gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_HB))) { - mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0); + mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0); ret = -EINVAL; goto out_free; } } } + ret = 0; out_free: kfree(data); @@ -1015,7 +1025,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) "PPAG capability not supported by FW, command not sent.\n"); return 0; } - if (!mvm->fwrt.ppag_table.v1.enabled) { + if (!mvm->fwrt.ppag_table.v1.flags) { IWL_DEBUG_RADIO(mvm, "PPAG not enabled, command not sent.\n"); return 0; } @@ -1024,20 +1034,28 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) PER_PLATFORM_ANT_GAIN_CMD, IWL_FW_CMD_VER_UNKNOWN); if (cmd_ver == 1) { - num_sub_bands = IWL_NUM_SUB_BANDS; + num_sub_bands = IWL_NUM_SUB_BANDS_V1; gain = mvm->fwrt.ppag_table.v1.gain[0]; cmd_size = sizeof(mvm->fwrt.ppag_table.v1); - if (mvm->fwrt.ppag_ver == 2) { + if (mvm->fwrt.ppag_ver == 1 || mvm->fwrt.ppag_ver == 2) { IWL_DEBUG_RADIO(mvm, - "PPAG table is v2 but FW supports v1, sending truncated table\n"); + "PPAG table rev is %d but FW supports v1, sending truncated table\n", + mvm->fwrt.ppag_ver); + mvm->fwrt.ppag_table.v1.flags &= + cpu_to_le32(IWL_PPAG_ETSI_MASK); } - } else if (cmd_ver == 2) { + } else if (cmd_ver == 2 || cmd_ver == 3) { num_sub_bands = IWL_NUM_SUB_BANDS_V2; gain = mvm->fwrt.ppag_table.v2.gain[0]; cmd_size = sizeof(mvm->fwrt.ppag_table.v2); - if (mvm->fwrt.ppag_ver == 1) { + if (mvm->fwrt.ppag_ver == 0) { IWL_DEBUG_RADIO(mvm, "PPAG table is v1 but FW supports v2, sending padded table\n"); + } else if (cmd_ver == 2 && mvm->fwrt.ppag_ver == 2) { + IWL_DEBUG_RADIO(mvm, + "PPAG table is v3 but FW supports v2, sending partial bitmap.\n"); + mvm->fwrt.ppag_table.v1.flags &= + cpu_to_le32(IWL_PPAG_ETSI_MASK); } } else { IWL_DEBUG_RADIO(mvm, "Unsupported PPAG command version\n"); @@ -1102,7 +1120,7 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) IWL_DEBUG_RADIO(mvm, "System vendor '%s' is not in the approved list, disabling PPAG.\n", dmi_get_system_info(DMI_SYS_VENDOR)); - mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0); + mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0); return 0; } From 9a0f28d8628ecf86841682784d4d34aac9b1d336 Mon Sep 17 00:00:00 2001 From: ybaruch Date: Wed, 31 Mar 2021 12:14:48 +0300 Subject: [PATCH 125/188] iwlwifi: add new so-gf device add new so-gf device to the driver. Signed-off-by: ybaruch Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.d6b0c1f85a7e.I2098ca066607edc48336021ea2e5afdbf8196acf@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index dd7e295397c8..729e5503f17a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2020 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1103,6 +1103,13 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_bz_a0_mr_a0, iwl_ma_name), +/* So with GF */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name) + #endif /* CONFIG_IWLMVM */ }; From 9cd243f24ec1960403de5f24f45155af24d94b13 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Wed, 31 Mar 2021 12:14:49 +0300 Subject: [PATCH 126/188] iwlwifi: move iwl_configure_rxq to be used by other op_modes All the op_modes need to send this command as well. Instead of duplicating the code from mvm, put the code in a common place. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.deb71fce883a.I5eef009512f180e5974f3f491ff56c763cdcc878@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/init.c | 59 ++++++++++++++++++ .../net/wireless/intel/iwlwifi/fw/runtime.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 61 +------------------ 3 files changed, 63 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 986913f2fbd5..2ecec00db9da 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -10,6 +10,8 @@ #include "fw/api/soc.h" #include "fw/api/commands.h" +#include "fw/api/rx.h" +#include "fw/api/datapath.h" void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, const struct iwl_fw *fw, @@ -95,3 +97,60 @@ int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt) return ret; } IWL_EXPORT_SYMBOL(iwl_set_soc_latency); + +int iwl_configure_rxq(struct iwl_fw_runtime *fwrt) +{ + int i, num_queues, size, ret; + struct iwl_rfh_queue_config *cmd; + struct iwl_host_cmd hcmd = { + .id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD), + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; + + /* + * The default queue is configured via context info, so if we + * have a single queue, there's nothing to do here. + */ + if (fwrt->trans->num_rx_queues == 1) + return 0; + + if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22000) + return 0; + + /* skip the default queue */ + num_queues = fwrt->trans->num_rx_queues - 1; + + size = struct_size(cmd, data, num_queues); + + cmd = kzalloc(size, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->num_queues = num_queues; + + for (i = 0; i < num_queues; i++) { + struct iwl_trans_rxq_dma_data data; + + cmd->data[i].q_num = i + 1; + iwl_trans_get_rxq_dma_data(fwrt->trans, i + 1, &data); + + cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb); + cmd->data[i].urbd_stts_wrptr = + cpu_to_le64(data.urbd_stts_wrptr); + cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb); + cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid); + } + + hcmd.data[0] = cmd; + hcmd.len[0] = size; + + ret = iwl_trans_send_cmd(fwrt->trans, &hcmd); + + kfree(cmd); + + if (ret) + IWL_ERR(fwrt, "Failed to configure RX queues: %d\n", ret); + + return ret; +} +IWL_EXPORT_SYMBOL(iwl_configure_rxq); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 0dba5444f2db..35af85a5430b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -190,5 +190,6 @@ void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt); void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt); int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt); +int iwl_configure_rxq(struct iwl_fw_runtime *fwrt); #endif /* __iwl_fw_runtime_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 4f297edd8e18..b8a25943a57d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -73,56 +73,6 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); } -static int iwl_configure_rxq(struct iwl_mvm *mvm) -{ - int i, num_queues, size, ret; - struct iwl_rfh_queue_config *cmd; - struct iwl_host_cmd hcmd = { - .id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD), - .dataflags[0] = IWL_HCMD_DFL_NOCOPY, - }; - - /* - * The default queue is configured via context info, so if we - * have a single queue, there's nothing to do here. - */ - if (mvm->trans->num_rx_queues == 1) - return 0; - - /* skip the default queue */ - num_queues = mvm->trans->num_rx_queues - 1; - - size = struct_size(cmd, data, num_queues); - - cmd = kzalloc(size, GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd->num_queues = num_queues; - - for (i = 0; i < num_queues; i++) { - struct iwl_trans_rxq_dma_data data; - - cmd->data[i].q_num = i + 1; - iwl_trans_get_rxq_dma_data(mvm->trans, i + 1, &data); - - cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb); - cmd->data[i].urbd_stts_wrptr = - cpu_to_le64(data.urbd_stts_wrptr); - cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb); - cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid); - } - - hcmd.data[0] = cmd; - hcmd.len[0] = size; - - ret = iwl_mvm_send_cmd(mvm, &hcmd); - - kfree(cmd); - - return ret; -} - static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm) { struct iwl_dqa_enable_cmd dqa_cmd = { @@ -1503,14 +1453,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) } /* Init RSS configuration */ - if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) { - ret = iwl_configure_rxq(mvm); - if (ret) { - IWL_ERR(mvm, "Failed to configure RX queues: %d\n", - ret); - goto error; - } - } + ret = iwl_configure_rxq(&mvm->fwrt); + if (ret) + goto error; if (iwl_mvm_has_new_rx_api(mvm)) { ret = iwl_send_rss_cfg_cmd(mvm); From d2bfda8addf9d78146c1ae3a39f4df3c845ea0d5 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 31 Mar 2021 12:14:50 +0300 Subject: [PATCH 127/188] iwlwifi: mvm: support BIOS enable/disable for 11ax in Ukraine Read the new BIOS DSM and Pass to FW if to disable\enable 11ax for Ukraine according to the BIOS key. this is needed to enable OEMs to control enable/disable 11ax in Ukraine Signed-off-by: Miri Korenblit Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.055654e7707e.If7eaf9839cd5d59729a235df07e31668b408e740@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 29 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 9 ++++++ .../wireless/intel/iwlwifi/fw/api/nvm-reg.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 4 +++ 4 files changed, 45 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 56c4d05c9cc2..874cc110d97f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -695,3 +695,32 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, return 0; } IWL_EXPORT_SYMBOL(iwl_sar_geo_init); + +u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev) +{ + union acpi_object *obj; + u32 ret; + + obj = iwl_acpi_get_dsm_object(dev, 0, + DSM_FUNC_11AX_ENABLEMENT, NULL, + &iwl_guid); + if (IS_ERR(obj)) + return 0; + + if (obj->type != ACPI_TYPE_INTEGER) { + IWL_DEBUG_DEV_RADIO(dev, + "ACPI: DSM method did not return a valid object, type=%d\n", + obj->type); + ret = 0; + goto out; + } + + ret = obj->integer.value; + IWL_DEBUG_DEV_RADIO(dev, + "ACPI: DSM method evaluated: func=DSM_FUNC_11AX_ENABLEMENT, ret=%d\n", + ret); +out: + ACPI_FREE(obj); + return ret; +} +IWL_EXPORT_SYMBOL(iwl_acpi_eval_dsm_11ax_enablement); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index f8ea588e4fbb..b7389f41a009 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -77,6 +77,7 @@ enum iwl_dsm_funcs_rev_0 { DSM_FUNC_QUERY = 0, DSM_FUNC_DISABLE_SRD = 1, DSM_FUNC_ENABLE_INDONESIA_5G2 = 2, + DSM_FUNC_11AX_ENABLEMENT = 6, }; enum iwl_dsm_values_srd { @@ -160,6 +161,8 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array, int *block_list_size); +u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev); + #else /* CONFIG_ACPI */ static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method) @@ -235,5 +238,11 @@ static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, { return -ENOENT; } + +static inline u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev) +{ + return 0; +} + #endif /* CONFIG_ACPI */ #endif /* __iwl_fw_acpi__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index fbca9dd872e7..3a358bbdde8e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -414,6 +414,9 @@ enum iwl_lari_config_masks { LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK = BIT(3), }; +#define IWL_11AX_UKRAINE_MASK 3 +#define IWL_11AX_UKRAINE_SHIFT 8 + /** * struct iwl_lari_config_change_cmd_v1 - change LARI configuration * @config_bitmap: bit map of the config commands. each bit will trigger a diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index b8a25943a57d..ff3967f7c66b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1213,6 +1213,10 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm) cmd.config_bitmap |= cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK); + ret = iwl_acpi_eval_dsm_11ax_enablement((&mvm->fwrt)->dev); + cmd.config_bitmap |= + cpu_to_le32((ret &= IWL_11AX_UKRAINE_MASK) << IWL_11AX_UKRAINE_SHIFT); + /* apply more config masks here */ if (cmd.config_bitmap) { From f21afabae70394aa2cf4bdee24f34884cdb93be1 Mon Sep 17 00:00:00 2001 From: Harish Mitty Date: Wed, 31 Mar 2021 12:14:51 +0300 Subject: [PATCH 128/188] iwlwifi: mvm: refactor ACPI DSM evaluation function Instead of implementing the DSM evaluation function in the MVM code, refactor it so it can be generalized and part of the common ACPI implementation. Signed-off-by: Harish Mitty [reworded subject and commit message] Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.a24af3551aac.I8e6bd5eb05f853b6331fa4823750f7ba8ffe46e6@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 58 +++++++++++++-- drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 76 +------------------- 3 files changed, 55 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 874cc110d97f..eecc76a6e408 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -696,20 +696,27 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, } IWL_EXPORT_SYMBOL(iwl_sar_geo_init); -u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev) +static u32 iwl_acpi_eval_dsm_func(struct device *dev, enum iwl_dsm_funcs_rev_0 eval_func) { union acpi_object *obj; u32 ret; obj = iwl_acpi_get_dsm_object(dev, 0, - DSM_FUNC_11AX_ENABLEMENT, NULL, + eval_func, NULL, &iwl_guid); - if (IS_ERR(obj)) + + if (IS_ERR(obj)) { + IWL_DEBUG_DEV_RADIO(dev, + "ACPI: DSM func '%d': Got Error in obj = %ld\n", + eval_func, + PTR_ERR(obj)); return 0; + } if (obj->type != ACPI_TYPE_INTEGER) { IWL_DEBUG_DEV_RADIO(dev, - "ACPI: DSM method did not return a valid object, type=%d\n", + "ACPI: DSM func '%d' did not return a valid object, type=%d\n", + eval_func, obj->type); ret = 0; goto out; @@ -717,10 +724,49 @@ u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev) ret = obj->integer.value; IWL_DEBUG_DEV_RADIO(dev, - "ACPI: DSM method evaluated: func=DSM_FUNC_11AX_ENABLEMENT, ret=%d\n", + "ACPI: DSM method evaluated: func='%d', ret=%d\n", + eval_func, ret); out: ACPI_FREE(obj); return ret; } -IWL_EXPORT_SYMBOL(iwl_acpi_eval_dsm_11ax_enablement); + +__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt) +{ + u32 ret; + __le32 config_bitmap = 0; + + /* + ** Evaluate func 'DSM_FUNC_ENABLE_INDONESIA_5G2' + */ + ret = iwl_acpi_eval_dsm_func(fwrt->dev, DSM_FUNC_ENABLE_INDONESIA_5G2); + + if (ret == DSM_VALUE_INDONESIA_ENABLE) + config_bitmap |= + cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK); + + /* + ** Evaluate func 'DSM_FUNC_DISABLE_SRD' + */ + ret = iwl_acpi_eval_dsm_func(fwrt->dev, DSM_FUNC_DISABLE_SRD); + + if (ret == DSM_VALUE_SRD_PASSIVE) + config_bitmap |= + cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK); + + else if (ret == DSM_VALUE_SRD_DISABLE) + config_bitmap |= + cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK); + + /* + ** Evaluate func 'DSM_FUNC_11AX_ENABLEMENT' + */ + ret = iwl_acpi_eval_dsm_func(fwrt->dev, DSM_FUNC_11AX_ENABLEMENT); + + config_bitmap |= + cpu_to_le32((ret &= IWL_11AX_UKRAINE_MASK) << IWL_11AX_UKRAINE_SHIFT); + + return config_bitmap; +} +IWL_EXPORT_SYMBOL(iwl_acpi_get_lari_config_bitmap); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index b7389f41a009..d16e6ec08c9f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -161,7 +161,7 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array, int *block_list_size); -u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev); +__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt); #else /* CONFIG_ACPI */ @@ -239,7 +239,7 @@ static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, return -ENOENT; } -static inline u32 iwl_acpi_eval_dsm_11ax_enablement(struct device *dev) +static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt) { return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index ff3967f7c66b..be831dd2c05c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1112,33 +1112,6 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret); } -static u8 iwl_mvm_eval_dsm_indonesia_5g2(struct iwl_mvm *mvm) -{ - u8 value; - - int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0, - DSM_FUNC_ENABLE_INDONESIA_5G2, - &iwl_guid, &value); - - if (ret < 0) - IWL_DEBUG_RADIO(mvm, - "Failed to evaluate DSM function ENABLE_INDONESIA_5G2, ret=%d\n", - ret); - - else if (value >= DSM_VALUE_INDONESIA_MAX) - IWL_DEBUG_RADIO(mvm, - "DSM function ENABLE_INDONESIA_5G2 return invalid value, value=%d\n", - value); - - else if (value == DSM_VALUE_INDONESIA_ENABLE) { - IWL_DEBUG_RADIO(mvm, - "Evaluated DSM function ENABLE_INDONESIA_5G2: Enabling 5g2\n"); - return DSM_VALUE_INDONESIA_ENABLE; - } - /* default behaviour is disabled */ - return DSM_VALUE_INDONESIA_DISABLE; -} - static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm) { u8 value; @@ -1163,59 +1136,12 @@ static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm) return DSM_VALUE_RFI_DISABLE; } -static u8 iwl_mvm_eval_dsm_disable_srd(struct iwl_mvm *mvm) -{ - u8 value; - int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0, - DSM_FUNC_DISABLE_SRD, - &iwl_guid, &value); - - if (ret < 0) - IWL_DEBUG_RADIO(mvm, - "Failed to evaluate DSM function DISABLE_SRD, ret=%d\n", - ret); - - else if (value >= DSM_VALUE_SRD_MAX) - IWL_DEBUG_RADIO(mvm, - "DSM function DISABLE_SRD return invalid value, value=%d\n", - value); - - else if (value == DSM_VALUE_SRD_PASSIVE) { - IWL_DEBUG_RADIO(mvm, - "Evaluated DSM function DISABLE_SRD: setting SRD to passive\n"); - return DSM_VALUE_SRD_PASSIVE; - - } else if (value == DSM_VALUE_SRD_DISABLE) { - IWL_DEBUG_RADIO(mvm, - "Evaluated DSM function DISABLE_SRD: disabling SRD\n"); - return DSM_VALUE_SRD_DISABLE; - } - /* default behaviour is active */ - return DSM_VALUE_SRD_ACTIVE; -} - static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm) { - u8 ret; int cmd_ret; struct iwl_lari_config_change_cmd_v2 cmd = {}; - if (iwl_mvm_eval_dsm_indonesia_5g2(mvm) == DSM_VALUE_INDONESIA_ENABLE) - cmd.config_bitmap |= - cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK); - - ret = iwl_mvm_eval_dsm_disable_srd(mvm); - if (ret == DSM_VALUE_SRD_PASSIVE) - cmd.config_bitmap |= - cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK); - - else if (ret == DSM_VALUE_SRD_DISABLE) - cmd.config_bitmap |= - cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK); - - ret = iwl_acpi_eval_dsm_11ax_enablement((&mvm->fwrt)->dev); - cmd.config_bitmap |= - cpu_to_le32((ret &= IWL_11AX_UKRAINE_MASK) << IWL_11AX_UKRAINE_SHIFT); + cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt); /* apply more config masks here */ From 098f1ea54e7ce80c39ecdf1b61a0939380674c1b Mon Sep 17 00:00:00 2001 From: Ravi Darsi Date: Wed, 31 Mar 2021 12:14:52 +0300 Subject: [PATCH 129/188] iwlwifi: mvm: Use IWL_INFO in fw_reset_handshake() Debug message "firmware didn't ACK the reset - continue anyway\n" in fw_reset_handshake() is classified as error, however this is not an error as it is ignored. So, change it to info message for proper classification of debug messages. Signed-off-by: Ravi Darsi Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210331121101.449b3092c330.I515edcc41913ca7fbe4a4de923671d120d5618c6@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 94ffc1ae484d..9d94c47952d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -108,8 +108,8 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) ret = wait_event_timeout(trans_pcie->fw_reset_waitq, trans_pcie->fw_reset_done, FW_RESET_TIMEOUT); if (!ret) - IWL_ERR(trans, - "firmware didn't ACK the reset - continue anyway\n"); + IWL_INFO(trans, + "firmware didn't ACK the reset - continue anyway\n"); } void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) From 0c73f47b430d125163ae42d7f271df1050cb993f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 11 Apr 2021 12:46:19 +0300 Subject: [PATCH 130/188] iwlwifi: remove TCM events Nobody uses that in the user space. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.b6560a5de0cd.I5dac9c60faed7f48b06d352aa2d65bcf8142c2dc@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 18 ++---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index e2a37ac7c4b1..4d9d4d6892fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -591,7 +591,6 @@ struct iwl_mvm_tcm { enum iwl_mvm_traffic_load global_load; bool low_latency[NUM_MAC_INDEX_DRIVER]; bool change[NUM_MAC_INDEX_DRIVER]; - bool global_change; } result; }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index b6b481ff1518..c566be99a4c7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1030,15 +1030,9 @@ iwl_mvm_tcm_load(struct iwl_mvm *mvm, u32 airtime, unsigned long elapsed) return IWL_MVM_TRAFFIC_LOW; } -struct iwl_mvm_tcm_iter_data { - struct iwl_mvm *mvm; - bool any_sent; -}; - static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { - struct iwl_mvm_tcm_iter_data *data = _data; - struct iwl_mvm *mvm = data->mvm; + struct iwl_mvm *mvm = _data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); bool low_latency, prev = mvmvif->low_latency & LOW_LATENCY_TRAFFIC; @@ -1060,22 +1054,15 @@ static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) } else { iwl_mvm_update_quotas(mvm, false, NULL); } - - data->any_sent = true; } static void iwl_mvm_tcm_results(struct iwl_mvm *mvm) { - struct iwl_mvm_tcm_iter_data data = { - .mvm = mvm, - .any_sent = false, - }; - mutex_lock(&mvm->mutex); ieee80211_iterate_active_interfaces( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_tcm_iter, &data); + iwl_mvm_tcm_iter, mvm); if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) iwl_mvm_config_scan(mvm); @@ -1257,7 +1244,6 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm, } load = iwl_mvm_tcm_load(mvm, total_airtime, elapsed); - mvm->tcm.result.global_change = load != mvm->tcm.result.global_load; mvm->tcm.result.global_load = load; for (i = 0; i < NUM_NL80211_BANDS; i++) { From fb54b86339adb6915a512d955d49d0d7f2aa4ba2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Apr 2021 12:46:20 +0300 Subject: [PATCH 131/188] iwlwifi: remove remaining software checksum code After the removal of the software checksum code for the A-MSDU path that we had for testing, the csum_skb variable stuck around. Remove it. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.280f268ae679.Iad455b6c91e427c9f74963bbd3eb0ce743aaac53@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 11 +++-------- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 11 +++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index b07194b74d97..0346505351f5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2003-2014, 2018-2020 Intel Corporation + * Copyright (C) 2003-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1350,7 +1350,6 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, /* this is the data left for this subframe */ unsigned int data_left = min_t(unsigned int, mss, total_len); - struct sk_buff *csum_skb = NULL; unsigned int hdr_tb_len; dma_addr_t hdr_tb_phys; u8 *subf_hdrs_start = hdr_page->pos; @@ -1381,10 +1380,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, hdr_tb_len = hdr_page->pos - start_hdr; hdr_tb_phys = dma_map_single(trans->dev, start_hdr, hdr_tb_len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(trans->dev, hdr_tb_phys))) { - dev_kfree_skb(csum_skb); + if (unlikely(dma_mapping_error(trans->dev, hdr_tb_phys))) return -EINVAL; - } iwl_pcie_txq_build_tfd(trans, txq, hdr_tb_phys, hdr_tb_len, false); trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, @@ -1403,10 +1400,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, tb_phys = dma_map_single(trans->dev, tso.data, size, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(trans->dev, tb_phys))) { - dev_kfree_skb(csum_skb); + if (unlikely(dma_mapping_error(trans->dev, tb_phys))) return -EINVAL; - } iwl_pcie_txq_build_tfd(trans, txq, tb_phys, size, false); diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index 833f43d1ca7a..494f9dbf92d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation */ #include #include @@ -399,7 +399,6 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, while (total_len) { /* this is the data left for this subframe */ unsigned int data_left = min_t(unsigned int, mss, total_len); - struct sk_buff *csum_skb = NULL; unsigned int tb_len; dma_addr_t tb_phys; u8 *subf_hdrs_start = hdr_page->pos; @@ -430,10 +429,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, tb_len = hdr_page->pos - start_hdr; tb_phys = dma_map_single(trans->dev, start_hdr, tb_len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(trans->dev, tb_phys))) { - dev_kfree_skb(csum_skb); + if (unlikely(dma_mapping_error(trans->dev, tb_phys))) goto out_err; - } /* * No need for _with_wa, this is from the TSO page and * we leave some space at the end of it so can't hit @@ -458,10 +455,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, ret = iwl_txq_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, tso.data, tb_len, NULL); - if (ret) { - dev_kfree_skb(csum_skb); + if (ret) goto out_err; - } data_left -= tb_len; tso_build_data(skb, &tso, tb_len); From 2b84e6328e65e263f62bae602894712449f41bc9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 11 Apr 2021 12:46:21 +0300 Subject: [PATCH 132/188] iwlwifi: don't warn if we can't wait for empty tx queues If the firmware is dead, the Tx queues won't drain, but leaving a print in the log is enough, no need to WARN. If the firmware is dead, we must already have printed enough information in the log anyway. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.9a438b2320a9.I4aa897178df82acefd80173d76dd6849ad1bcdc1@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 4a5822c1be13..6abb7385dae1 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2020 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1267,7 +1267,8 @@ static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, if (WARN_ON_ONCE(!trans->ops->wait_tx_queues_empty)) return -ENOTSUPP; - if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) { + /* No need to wait if the firmware is not alive */ + if (trans->state != IWL_TRANS_FW_ALIVE) { IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); return -EIO; } From 4cf2f5904d971a461f67825434ae3c31900ff84b Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 11 Apr 2021 12:46:22 +0300 Subject: [PATCH 133/188] iwlwifi: queue: avoid memory leak in reset flow In case the device is stopped any usage of hw queues needs to be reallocated in fw due to fw reset after device stop, so all driver internal queue should also be freed, and if we don't free the next usage would leak the old memory and get in recover flows "iwlwifi 0000:00:03.0: dma_pool_destroy iwlwifi:bc" warning. Also warn about trying to reuse an internal allocated queue. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.c72d2f0355c4.Ia3baff633b9b9109f88ab379ef0303aa152c16bf@changeid Signed-off-by: Luca Coelho --- .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 4 +-- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 30 ++++--------------- drivers/net/wireless/intel/iwlwifi/queue/tx.h | 3 +- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 9d94c47952d1..1bcd36e9e008 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include "iwl-trans.h" #include "iwl-prph.h" @@ -143,7 +143,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); - iwl_txq_gen2_tx_stop(trans); + iwl_txq_gen2_tx_free(trans); iwl_pcie_rx_stop(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index 494f9dbf92d6..451b06069350 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -13,30 +13,6 @@ #include "iwl-scd.h" #include -/* - * iwl_txq_gen2_tx_stop - Stop all Tx DMA channels - */ -void iwl_txq_gen2_tx_stop(struct iwl_trans *trans) -{ - int txq_id; - - /* - * This function can be called before the op_mode disabled the - * queues. This happens when we have an rfkill interrupt. - * Since we stop Tx altogether - mark the queues as stopped. - */ - memset(trans->txqs.queue_stopped, 0, - sizeof(trans->txqs.queue_stopped)); - memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used)); - - /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < ARRAY_SIZE(trans->txqs.txq); txq_id++) { - if (!trans->txqs.txq[txq_id]) - continue; - iwl_txq_gen2_unmap(trans, txq_id); - } -} - /* * iwl_txq_update_byte_tbl - Set up entry in Tx byte-count array */ @@ -1184,6 +1160,12 @@ static int iwl_txq_alloc_response(struct iwl_trans *trans, struct iwl_txq *txq, goto error_free_resp; } + if (WARN_ONCE(trans->txqs.txq[qid], + "queue %d already allocated\n", qid)) { + ret = -EIO; + goto error_free_resp; + } + txq->id = qid; trans->txqs.txq[qid] = txq; wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1); diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h index af1dbdf5617a..20efc62acf13 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation */ #ifndef __iwl_trans_queue_tx_h__ #define __iwl_trans_queue_tx_h__ @@ -123,7 +123,6 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, void iwl_txq_dyn_free(struct iwl_trans *trans, int queue); void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq); void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq); -void iwl_txq_gen2_tx_stop(struct iwl_trans *trans); void iwl_txq_gen2_tx_free(struct iwl_trans *trans); int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, bool cmd_queue); From 4f7411d648939dfac596a7af8f28fc6eeb9833e8 Mon Sep 17 00:00:00 2001 From: Roee Goldfiner Date: Sun, 11 Apr 2021 12:46:23 +0300 Subject: [PATCH 134/188] iwlwifi: mvm: umac error table mismatch umac_error_table In TLV address was read using mask on MSB but on the same table in alive message it was without which caused mismatch in devices with different memory region MSB Signed-off-by: Roee Goldfiner Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.179fee442115.Ib6eabe86cfda0b6044f07c07448c366b6e07e53d@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/img.h | 5 ++++- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 4 +--- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 1dee4714e505..153a3529e77a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2020 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Intel Deutschland GmbH */ @@ -116,6 +116,9 @@ struct fw_img { #define PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS 0 #define PAGING_TLV_SECURE_MASK 1 +/* FW MSB Mask for regions/cache_control */ +#define FW_ADDR_CACHE_CONTROL 0xC0000000UL + /** * struct iwl_fw_paging * @fw_paging_phys: page phy pointer diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index eb168dc535d4..884750bf7840 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2020 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -550,8 +550,6 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, return 0; } -#define FW_ADDR_CACHE_CONTROL 0xC0000000 - static int iwl_parse_tlv_firmware(struct iwl_drv *drv, const struct firmware *ucode_raw, struct iwl_firmware_pieces *pieces, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index be831dd2c05c..9a3981f43050 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -186,7 +186,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, mvm->trans->dbg.lmac_error_event_table[1] = le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr); - umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr); + umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr) & + ~FW_ADDR_CACHE_CONTROL; if (umac_error_table) { if (umac_error_table >= From aa1540ca7616b996327abb8cb6f19ee91b34dbe0 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 11 Apr 2021 12:46:24 +0300 Subject: [PATCH 135/188] iwlwifi: mvm: remove PS from lower rates. Power save (PS) should only be enabled when we reach the max phy rate. Before we reach it (MCS_9) for VHT, we should keep trying to improve the throughput. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.2a2fb9f9c25e.I7c7bbcfbdc1d35d2c3338778fb397dd5b08ea0e8@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 91b6541d579f..b97708cb869d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /****************************************************************************** * - * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * @@ -1926,9 +1926,7 @@ static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (is_ht(rate)) return index == IWL_RATE_MCS_7_INDEX; if (is_vht(rate)) - return index == IWL_RATE_MCS_7_INDEX || - index == IWL_RATE_MCS_8_INDEX || - index == IWL_RATE_MCS_9_INDEX; + return index == IWL_RATE_MCS_9_INDEX; WARN_ON_ONCE(1); return false; From 6da29d3b42ea8b23251f8312e083a8da2e5ed6eb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Apr 2021 12:46:25 +0300 Subject: [PATCH 136/188] iwlwifi: mvm: don't lock mutex in RCU critical section We cannot lock a mutex while we're in an RCU critical section. At the same time, we're accessing data structures that are protected by the mvm->mutex anyway, so just move the entire locking here to use only that. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.4d27bd36e10e.I1fd8e8fe442c41a5deaa560452b598ed7a60ada5@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 34ddef97b099..63d65018d098 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1210,10 +1210,10 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE)) return -EINVAL; - rcu_read_lock(); + mutex_lock(&mvm->mutex); for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) { - vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true); + vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false); if (!vif) continue; @@ -1253,18 +1253,16 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) &beacon_cmd.tim_size, beacon->data, beacon->len); - mutex_lock(&mvm->mutex); iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd, sizeof(beacon_cmd)); mutex_unlock(&mvm->mutex); dev_kfree_skb(beacon); - rcu_read_unlock(); return 0; out_err: - rcu_read_unlock(); + mutex_unlock(&mvm->mutex); return -EINVAL; } From 2b6166664d2b5553953a8a5dee0843f3b1ca18e2 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 11 Apr 2021 12:46:26 +0300 Subject: [PATCH 137/188] iwlwifi: pcie: merge napi_poll_msix functions The only difference between iwl_pcie_napi_poll_msix_shared() and iwl_pcie_napi_poll_msix() is when we have a shared queue and nothing in the rx queue. This case doesn't affect CPU performance, so we can merge the two functions. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.9d1b61ef53a5.I60b33d5379cf7c12f1de30fc3fd4cefc38220141@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 47 +++++--------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 0cbc79949982..e4607f943ac3 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2003-2014, 2018-2020 Intel Corporation + * Copyright (C) 2003-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1046,33 +1046,19 @@ static int iwl_pcie_napi_poll_msix(struct napi_struct *napi, int budget) trans = trans_pcie->trans; ret = iwl_pcie_rx_handle(trans, rxq->id, budget); + IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n", rxq->id, ret, + budget); if (ret < budget) { + int irq_line = rxq->id; + + /* FIRST_RSS is shared with line 0 */ + if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS && + rxq->id == 1) + irq_line = 0; + spin_lock(&trans_pcie->irq_lock); - iwl_pcie_clear_irq(trans, rxq->id); - spin_unlock(&trans_pcie->irq_lock); - - napi_complete_done(&rxq->napi, ret); - } - - return ret; -} - -static int iwl_pcie_napi_poll_msix_shared(struct napi_struct *napi, int budget) -{ - struct iwl_rxq *rxq = container_of(napi, struct iwl_rxq, napi); - struct iwl_trans_pcie *trans_pcie; - struct iwl_trans *trans; - int ret; - - trans_pcie = container_of(napi->dev, struct iwl_trans_pcie, napi_dev); - trans = trans_pcie->trans; - - ret = iwl_pcie_rx_handle(trans, rxq->id, budget); - - if (ret < budget) { - spin_lock(&trans_pcie->irq_lock); - iwl_pcie_clear_irq(trans, 0); + iwl_pcie_clear_irq(trans, irq_line); spin_unlock(&trans_pcie->irq_lock); napi_complete_done(&rxq->napi, ret); @@ -1134,18 +1120,9 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans) if (!rxq->napi.poll) { int (*poll)(struct napi_struct *, int) = iwl_pcie_napi_poll; - if (trans_pcie->msix_enabled) { + if (trans_pcie->msix_enabled) poll = iwl_pcie_napi_poll_msix; - if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX && - i == 0) - poll = iwl_pcie_napi_poll_msix_shared; - - if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS && - i == 1) - poll = iwl_pcie_napi_poll_msix_shared; - } - netif_napi_add(&trans_pcie->napi_dev, &rxq->napi, poll, NAPI_POLL_WEIGHT); napi_enable(&rxq->napi); From 9d401222db54dac353fecad26f2610c12c33ef47 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 11 Apr 2021 12:46:27 +0300 Subject: [PATCH 138/188] iwlwifi: pcie: add ISR debug info for msix debug The debug prints help in case we get timeout on waiting for hw. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124417.306e2e56d3e8.I72e2977abbb1fddf23b8476bedf6a183fe969ff5@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 16 +++++++++++----- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 5 +++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index e4607f943ac3..fb8491412be4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1023,6 +1023,9 @@ static int iwl_pcie_napi_poll(struct napi_struct *napi, int budget) ret = iwl_pcie_rx_handle(trans, rxq->id, budget); + IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n", + rxq->id, ret, budget); + if (ret < budget) { spin_lock(&trans_pcie->irq_lock); if (test_bit(STATUS_INT_ENABLED, &trans->status)) @@ -1636,10 +1639,13 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id) if (WARN_ON(entry->entry >= trans->num_rx_queues)) return IRQ_NONE; - if (WARN_ONCE(!rxq, "Got MSI-X interrupt before we have Rx queues")) + if (WARN_ONCE(!rxq, + "[%d] Got MSI-X interrupt before we have Rx queues", + entry->entry)) return IRQ_NONE; lock_map_acquire(&trans->sync_cmd_lockdep_map); + IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry); local_bh_disable(); if (napi_schedule_prep(&rxq->napi)) @@ -2203,8 +2209,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) if (iwl_have_debug_level(IWL_DL_ISR)) { IWL_DEBUG_ISR(trans, - "ISR inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n", - inta_fh, trans_pcie->fh_mask, + "ISR[%d] inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n", + entry->entry, inta_fh, trans_pcie->fh_mask, iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD)); if (inta_fh & ~trans_pcie->fh_mask) IWL_DEBUG_ISR(trans, @@ -2259,8 +2265,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) /* After checking FH register check HW register */ if (iwl_have_debug_level(IWL_DL_ISR)) { IWL_DEBUG_ISR(trans, - "ISR inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n", - inta_hw, trans_pcie->hw_mask, + "ISR[%d] inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n", + entry->entry, inta_hw, trans_pcie->hw_mask, iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD)); if (inta_hw & ~trans_pcie->hw_mask) IWL_DEBUG_ISR(trans, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 1bf4c37fe960..861dbc03d183 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1604,6 +1604,11 @@ iwl_pcie_set_interrupt_capa(struct pci_dev *pdev, } else { trans_pcie->trans->num_rx_queues = num_irqs - 1; } + + IWL_DEBUG_INFO(trans, + "MSI-X enabled with rx queues %d, vec mask 0x%x\n", + trans_pcie->trans->num_rx_queues, trans_pcie->shared_vec_mask); + WARN_ON(trans_pcie->trans->num_rx_queues > IWL_MAX_RX_HW_QUEUES); trans_pcie->alloc_vecs = num_irqs; From 3c21990b0ccecf0e3679f82cd1931999bd78b261 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 11 Apr 2021 12:46:28 +0300 Subject: [PATCH 139/188] iwlwifi: mvm: add support for version 3 of LARI_CONFIG_CHANGE command. Add support for version 3 of the LARI_CONFIG_CHANGE command. This is needed to support FW API change which is needed to support 11ax enablement in Russia. Signed-off-by: Miri Korenblit Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124418.7e68856c8a95.I83acdbe39b63c363cabc04ad42d1d0b9ce98901c@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 10 +--------- .../wireless/intel/iwlwifi/fw/api/nvm-reg.h | 17 ++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 18 ++++++++++++------ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index eecc76a6e408..e31bba836c6f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation */ #include #include "iwl-drv.h" @@ -759,14 +759,6 @@ __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt) config_bitmap |= cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK); - /* - ** Evaluate func 'DSM_FUNC_11AX_ENABLEMENT' - */ - ret = iwl_acpi_eval_dsm_func(fwrt->dev, DSM_FUNC_11AX_ENABLEMENT); - - config_bitmap |= - cpu_to_le32((ret &= IWL_11AX_UKRAINE_MASK) << IWL_11AX_UKRAINE_SHIFT); - return config_bitmap; } IWL_EXPORT_SYMBOL(iwl_acpi_get_lari_config_bitmap); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 3a358bbdde8e..dc8f2777e944 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -437,6 +437,21 @@ struct iwl_lari_config_change_cmd_v2 { __le32 oem_uhb_allow_bitmap; } __packed; /* LARI_CHANGE_CONF_CMD_S_VER_2 */ +/** + * struct iwl_lari_config_change_cmd_v3 - change LARI configuration + * @config_bitmap: bit map of the config commands. each bit will trigger a + * different predefined FW config operation + * @oem_uhb_allow_bitmap: bitmap of UHB enabled MCC sets + * @oem_11ax_allow_bitmap: bitmap of 11ax allowed MCCs. + * For each supported country, a pair of regulatory override bit and 11ax mode exist + * in the bit field. + */ +struct iwl_lari_config_change_cmd_v3 { + __le32 config_bitmap; + __le32 oem_uhb_allow_bitmap; + __le32 oem_11ax_allow_bitmap; +} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_3 */ + /** * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete * @status: PNVM image loading status diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 9a3981f43050..8aa5f1a2c58c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1140,18 +1140,24 @@ static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm) static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm) { int cmd_ret; - struct iwl_lari_config_change_cmd_v2 cmd = {}; + struct iwl_lari_config_change_cmd_v3 cmd = {}; cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt); /* apply more config masks here */ if (cmd.config_bitmap) { - size_t cmd_size = iwl_fw_lookup_cmd_ver(mvm->fw, - REGULATORY_AND_NVM_GROUP, - LARI_CONFIG_CHANGE, 1) == 2 ? - sizeof(struct iwl_lari_config_change_cmd_v2) : - sizeof(struct iwl_lari_config_change_cmd_v1); + size_t cmd_size; + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, + REGULATORY_AND_NVM_GROUP, + LARI_CONFIG_CHANGE, 1); + if (cmd_ver == 3) + cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3); + else if (cmd_ver == 2) + cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2); + else + cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1); + IWL_DEBUG_RADIO(mvm, "sending LARI_CONFIG_CHANGE, config_bitmap=0x%x\n", le32_to_cpu(cmd.config_bitmap)); From 70c9101d0a3e499b418e119d475d0e4533409e08 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Apr 2021 12:46:29 +0300 Subject: [PATCH 140/188] iwlwifi: warn on SKB free w/o op-mode If this ever happens, and it looks like some code in PCIe is a bit broken and might lead to this, we want to know without crashing, so add a WARN_ON_ONCE(). Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124418.a18b7443dc55.Ia29836738acf14a55af5504aba90c6fea9fff785@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h index e6d2e0994317..cf9c64090014 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2020 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 Intel Deutschland GmbH */ @@ -176,6 +176,8 @@ iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, bool state) static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) { + if (WARN_ON_ONCE(!op_mode)) + return; op_mode->ops->free_skb(op_mode, skb); } From a9174578262b86f15cb1882f35e53b1fae0649fd Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 11 Apr 2021 12:46:30 +0300 Subject: [PATCH 141/188] iwlwifi: rs-fw: don't support stbc for HE 160 Our HE doesn't support it so never set HE 160 stbc Fixes: 3e467b8e4cf4 ("iwlwifi: rs-fw: enable STBC in he correctly") Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411124418.550fd1903eb7.I8ddbc2f87044a5ef78d916c9c59be797811a1b7f@changeid Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 8772b65c9dab..2d58cb969918 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include "rs.h" #include "fw-api.h" @@ -72,19 +72,15 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm, bool vht_ena = vht_cap->vht_supported; u16 flags = 0; + /* get STBC flags */ if (mvm->cfg->ht_params->stbc && (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) { - if (he_cap->has_he) { - if (he_cap->he_cap_elem.phy_cap_info[2] & - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) - flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; - - if (he_cap->he_cap_elem.phy_cap_info[7] & - IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ) - flags |= IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK; - } else if ((ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) || - (vht_ena && - (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))) + if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] & + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) + flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; + else if (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; + else if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; } From cc61d3ced2aac08230f20809378c5e3134f6702d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 11 Apr 2021 13:25:38 +0300 Subject: [PATCH 142/188] iwlwifi: mvm: don't disconnect immediately if we don't hear beacons after CSA When we switch channel, we may miss a few beacons on the new channel. Don't disconnect if the time event for the switch ends before we hear the beacons. Note that this is relevant only for old devices that still use the TIME_EVENT firmware API for channel switch. The check that we hear a beacon before the time event ends was meant to be used for the association time event and not for the channel switch time event. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.3d710091a0bd.I37a161ffdfb099a10080fbdc3b70a4deb76952e2@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 1418a6438635..76c36f5cf9a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH */ @@ -294,6 +294,17 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, iwl_mvm_roc_finished(mvm); break; case NL80211_IFTYPE_STATION: + /* + * If we are switching channel, don't disconnect + * if the time event is already done. Beacons can + * be delayed a bit after the switch. + */ + if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) { + IWL_DEBUG_TE(mvm, + "No beacon heard and the CS time event is over, don't disconnect\n"); + break; + } + /* * By now, we should have finished association * and know the dtim period. From 997254a9169c9a8fab1c8408db4ef64a4081f4ce Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 11 Apr 2021 13:25:39 +0300 Subject: [PATCH 143/188] iwlwifi: mvm: don't WARN if we can't remove a time event It is not very useful to WARN if we can't send a host command The firmware is likely in a bad situation and the fact that we didn't send the host command has an impact on the firmware only, not on the driver. The driver could clean up all its state. Don't WARN in this case, but just leave a smaller note. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.0324abc169c8.I4f9b769bc38d68f8ed43f77d2cd75e8f1993e964@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 76c36f5cf9a3..83342a6a6d5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -734,8 +734,8 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, sizeof(time_cmd), &time_cmd); - if (WARN_ON(ret)) - return; + if (ret) + IWL_ERR(mvm, "Couldn't remove the time event\n"); } /* From 7db67f68392c1c5a6373c1caa7dd951bf94e550b Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Sun, 11 Apr 2021 13:25:40 +0300 Subject: [PATCH 144/188] iwlwifi: bump FW API to 63 for AX devices Start supporting API version 63 for AX devices. Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.a588a9dacd98.Ie4f96b8988c2cbd5f096ee64d0eb0f4829d55aee@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index d775cd9c1394..44735a6d1d39 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -9,7 +9,7 @@ #include "iwl-prph.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 62 +#define IWL_22000_UCODE_API_MAX 63 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 From d12455fdbfe9430affd88bfbfee51777356667a0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Apr 2021 13:25:41 +0300 Subject: [PATCH 145/188] iwlwifi: trans/pcie: defer transport initialisation In a few PCIe devices we may have to swap out the configuration after we allocate/initialise some parts of the device because we only know the correct one after reading some registers. This causes some things such as the byte-count table allocations to be incorrect, since the configuration is swapped for one with a bigger queue size. Fix this by initialising most of the transport much later, only after the configuration has finally been determined. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.8f5db97db1e4.Ic622da559b586a04ca536a0ec49ed5ecf03a9354@changeid Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/iwl-trans.c | 107 ++++++++++-------- .../net/wireless/intel/iwlwifi/iwl-trans.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 + 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 60e0db4a5e20..9236f9106826 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation */ #include #include @@ -21,7 +21,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, const struct iwl_cfg_trans_params *cfg_trans) { struct iwl_trans *trans; - int txcmd_size, txcmd_align; #ifdef CONFIG_LOCKDEP static struct lock_class_key __key; #endif @@ -31,23 +30,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, return NULL; trans->trans_cfg = cfg_trans; - if (!cfg_trans->gen2) { - txcmd_size = sizeof(struct iwl_tx_cmd); - txcmd_align = sizeof(void *); - } else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) { - txcmd_size = sizeof(struct iwl_tx_cmd_gen2); - txcmd_align = 64; - } else { - txcmd_size = sizeof(struct iwl_tx_cmd_gen3); - txcmd_align = 128; - } - - txcmd_size += sizeof(struct iwl_cmd_header); - txcmd_size += 36; /* biggest possible 802.11 header */ - - /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ - if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align)) - return ERR_PTR(-EINVAL); #ifdef CONFIG_LOCKDEP lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", @@ -58,22 +40,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, trans->ops = ops; trans->num_rx_queues = 1; - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) - trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); - else - trans->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl); - /* - * For gen2 devices, we use a single allocation for each byte-count - * table, but they're pretty small (1k) so use a DMA pool that we - * allocate here. - */ - if (trans->trans_cfg->gen2) { - trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", dev, - trans->txqs.bc_tbl_size, - 256, 0); - if (!trans->txqs.bc_pool) - return NULL; - } + WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); if (trans->trans_cfg->use_tfh) { trans->txqs.tfd.addr_size = 64; @@ -86,6 +53,52 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, } trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); + return trans; +} + +int iwl_trans_init(struct iwl_trans *trans) +{ + int txcmd_size, txcmd_align; + + if (!trans->trans_cfg->gen2) { + txcmd_size = sizeof(struct iwl_tx_cmd); + txcmd_align = sizeof(void *); + } else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { + txcmd_size = sizeof(struct iwl_tx_cmd_gen2); + txcmd_align = 64; + } else { + txcmd_size = sizeof(struct iwl_tx_cmd_gen3); + txcmd_align = 128; + } + + txcmd_size += sizeof(struct iwl_cmd_header); + txcmd_size += 36; /* biggest possible 802.11 header */ + + /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ + if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align)) + return -EINVAL; + + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); + else + trans->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl); + /* + * For gen2 devices, we use a single allocation for each byte-count + * table, but they're pretty small (1k) so use a DMA pool that we + * allocate here. + */ + if (trans->trans_cfg->gen2) { + trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev, + trans->txqs.bc_tbl_size, + 256, 0); + if (!trans->txqs.bc_pool) + return -ENOMEM; + } + + /* Some things must not change even if the config does */ + WARN_ON(trans->txqs.tfd.addr_size != + (trans->trans_cfg->use_tfh ? 64 : 36)); + snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); trans->dev_cmd_pool = @@ -93,36 +106,36 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, txcmd_size, txcmd_align, SLAB_HWCACHE_ALIGN, NULL); if (!trans->dev_cmd_pool) - return NULL; - - WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); + return -ENOMEM; trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); if (!trans->txqs.tso_hdr_page) { kmem_cache_destroy(trans->dev_cmd_pool); - return NULL; + return -ENOMEM; } /* Initialize the wait queue for commands */ init_waitqueue_head(&trans->wait_command_queue); - return trans; + return 0; } void iwl_trans_free(struct iwl_trans *trans) { int i; - for_each_possible_cpu(i) { - struct iwl_tso_hdr_page *p = - per_cpu_ptr(trans->txqs.tso_hdr_page, i); + if (trans->txqs.tso_hdr_page) { + for_each_possible_cpu(i) { + struct iwl_tso_hdr_page *p = + per_cpu_ptr(trans->txqs.tso_hdr_page, i); - if (p->page) - __free_page(p->page); + if (p && p->page) + __free_page(p->page); + } + + free_percpu(trans->txqs.tso_hdr_page); } - free_percpu(trans->txqs.tso_hdr_page); - kmem_cache_destroy(trans->dev_cmd_pool); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 6abb7385dae1..bf569f856ad8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1439,6 +1439,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct device *dev, const struct iwl_trans_ops *ops, const struct iwl_cfg_trans_params *cfg_trans); +int iwl_trans_init(struct iwl_trans *trans); void iwl_trans_free(struct iwl_trans *trans); /***************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 729e5503f17a..e33e559f847a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1276,6 +1276,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; } + ret = iwl_trans_init(iwl_trans); + if (ret) + goto out_free_trans; + pci_set_drvdata(pdev, iwl_trans); iwl_trans->drv = iwl_drv_start(iwl_trans); From 378c7be65ccd173762242805f4591618249b91ae Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Apr 2021 13:25:42 +0300 Subject: [PATCH 146/188] iwlwifi: fw: print out trigger delay when collecting data It can be confusing to see "Collecting data: ..." followed by that not actually happening immediately so print out the delay in that message. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.5bd095dc579a.Id1f3b746ac61497951638ba7ce70fc4b63dd87d1@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 504729663c35..cc4e18ca9566 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2559,7 +2559,9 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, fwrt->dump.wks[idx].dump_data = *dump_data; - IWL_WARN(fwrt, "WRT: Collecting data: ini trigger %d fired.\n", tp_id); + IWL_WARN(fwrt, + "WRT: Collecting data: ini trigger %d fired (delay=%dms).\n", + tp_id, (u32)(delay / USEC_PER_MSEC)); schedule_delayed_work(&fwrt->dump.wks[idx].wk, usecs_to_jiffies(delay)); From 8932abef6ea433228aea0e39eb237b244ae2b091 Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Sun, 11 Apr 2021 13:25:43 +0300 Subject: [PATCH 147/188] iwlwifi: pcie: Change ma product string name Change ma product string name to the correct name, and to reflect the CRF and not the CNV. Signed-off-by: Matti Gottlieb Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.c05b4c55540f.I8dd0361b033f63658999ba53640949701b048f17@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 44735a6d1d39..c2315dea9a23 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -388,8 +388,8 @@ const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203"; const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; +const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz"; const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz"; -const char iwl_ma_name[] = "Intel(R) Wi-Fi 6"; const char iwl_ax200_killer_1650w_name[] = "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)"; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index bdf352e97f51..b35ffdfdf14b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -505,8 +505,8 @@ extern const char iwl_ax201_killer_1650s_name[]; extern const char iwl_ax201_killer_1650i_name[]; extern const char iwl_ax210_killer_1675w_name[]; extern const char iwl_ax210_killer_1675x_name[]; -extern const char iwl_ma_name[]; extern const char iwl_ax211_name[]; +extern const char iwl_ax221_name[]; extern const char iwl_ax411_name[]; #if IS_ENABLED(CONFIG_IWLDVM) extern const struct iwl_cfg iwl5300_agn_cfg; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index e33e559f847a..d94bd8d732e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1028,12 +1028,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_cfg_ma_a0_mr_a0, iwl_ma_name), + iwl_cfg_ma_a0_mr_a0, iwl_ax221_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_cfg_snj_a0_mr_a0, iwl_ma_name), + iwl_cfg_snj_a0_mr_a0, iwl_ax221_name), /* So with Hr */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, @@ -1101,7 +1101,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_cfg_bz_a0_mr_a0, iwl_ma_name), + iwl_cfg_bz_a0_mr_a0, iwl_ax211_name), /* So with GF */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, From 7c81a025054cd0aeeeaf17aba2e9757f0a6a38a1 Mon Sep 17 00:00:00 2001 From: Mukesh Sisodiya Date: Sun, 11 Apr 2021 13:25:44 +0300 Subject: [PATCH 148/188] iwlwifi: dbg: disable ini debug in 9000 family and below Yoyo based debug is not applicable to old devices. As init debug is enabled by default in the driver, it needs to be disabled to work the old debug mechanism in old devices. Signed-off-by: Mukesh Sisodiya Fixes: b0d8d2c27007 ("iwlwifi: yoyo: enable yoyo by default") Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.805401a1b8ec.I30db38184a418cfc1c5ca1a305cc14a52501d415@changeid Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 579bc81cc0ae..4cd8c39cc3e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include #include "iwl-drv.h" @@ -426,7 +426,8 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans) const struct firmware *fw; int res; - if (!iwlwifi_mod_params.enable_ini) + if (!iwlwifi_mod_params.enable_ini || + trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_9000) return; res = firmware_request_nowarn(&fw, "iwl-debug-yoyo.bin", dev); From 1c22233a745e46dbc11db30d1f65aaae01e26eb5 Mon Sep 17 00:00:00 2001 From: Chen Lin Date: Tue, 16 Feb 2021 11:41:58 +0800 Subject: [PATCH 149/188] cw1200: Remove unused function pointer typedef cw1200_wsm_handler Remove the 'cw1200_wsm_handler' typedef as it is not used. Signed-off-by: Chen Lin Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1613446918-4532-1-git-send-email-chen45464546@163.com --- drivers/net/wireless/st/cw1200/bh.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/st/cw1200/bh.c b/drivers/net/wireless/st/cw1200/bh.c index c364a3987618..8bade5d89f12 100644 --- a/drivers/net/wireless/st/cw1200/bh.c +++ b/drivers/net/wireless/st/cw1200/bh.c @@ -42,9 +42,6 @@ enum cw1200_bh_pm_state { CW1200_BH_RESUME, }; -typedef int (*cw1200_wsm_handler)(struct cw1200_common *priv, - u8 *data, size_t size); - static void cw1200_bh_work(struct work_struct *work) { struct cw1200_common *priv = From 9dc5fdc8c4f889bd9ea5b6aa8b9d47ff9acef47e Mon Sep 17 00:00:00 2001 From: Chen Lin Date: Tue, 16 Feb 2021 12:30:33 +0800 Subject: [PATCH 150/188] cw1200: Remove unused function pointer typedef wsm_* Remove the 'wsm_*' typedef as it is not used. Signed-off-by: Chen Lin Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1613449833-4910-1-git-send-email-chen45464546@163.com --- drivers/net/wireless/st/cw1200/wsm.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/net/wireless/st/cw1200/wsm.h b/drivers/net/wireless/st/cw1200/wsm.h index 1ffa47994bb9..89fdc9115e9d 100644 --- a/drivers/net/wireless/st/cw1200/wsm.h +++ b/drivers/net/wireless/st/cw1200/wsm.h @@ -785,8 +785,6 @@ struct wsm_tx_confirm { }; /* 3.15 */ -typedef void (*wsm_tx_confirm_cb) (struct cw1200_common *priv, - struct wsm_tx_confirm *arg); /* Note that ideology of wsm_tx struct is different against the rest of * WSM API. wsm_hdr is /not/ a caller-adapted struct to be used as an input @@ -862,9 +860,6 @@ struct wsm_rx { /* = sizeof(generic hi hdr) + sizeof(wsm hdr) */ #define WSM_RX_EXTRA_HEADROOM (16) -typedef void (*wsm_rx_cb) (struct cw1200_common *priv, struct wsm_rx *arg, - struct sk_buff **skb_p); - /* 3.17 */ struct wsm_event { /* WSM_STATUS_... */ @@ -1180,8 +1175,6 @@ struct wsm_switch_channel { int wsm_switch_channel(struct cw1200_common *priv, const struct wsm_switch_channel *arg); -typedef void (*wsm_channel_switch_cb) (struct cw1200_common *priv); - #define WSM_START_REQ_ID 0x0017 #define WSM_START_RESP_ID 0x0417 @@ -1240,8 +1233,6 @@ int wsm_start_find(struct cw1200_common *priv); int wsm_stop_find(struct cw1200_common *priv); -typedef void (*wsm_find_complete_cb) (struct cw1200_common *priv, u32 status); - struct wsm_suspend_resume { /* See 3.52 */ /* Link ID */ @@ -1256,9 +1247,6 @@ struct wsm_suspend_resume { /* [out] */ int queue; }; -typedef void (*wsm_suspend_resume_cb) (struct cw1200_common *priv, - struct wsm_suspend_resume *arg); - /* 3.54 Update-IE request. */ struct wsm_update_ie { /* WSM_UPDATE_IE_... */ From 18fb0bedb5fc2fddc057dbe48b7360a6ffda34b3 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 19 Feb 2021 13:26:07 +0800 Subject: [PATCH 151/188] rtlwifi: 8821ae: upgrade PHY and RF parameters The signal strength of 5G is quite low, so user can't connect to an AP far away. New parameters with new format and its parser are updated by the commit 84d26fda52e2 ("rtlwifi: Update 8821ae new phy parameters and its parser."), but some parameters are missing. Use this commit to update to the novel parameters that use new format. Fixes: 84d26fda52e2 ("rtlwifi: Update 8821ae new phy parameters and its parser") Signed-off-by: Ping-Ke Shih Tested-by: Kai-Heng Feng Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210219052607.7323-1-pkshih@realtek.com --- .../realtek/rtlwifi/rtl8821ae/table.c | 558 +++++++++++++----- 1 file changed, 399 insertions(+), 159 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c index 27c8a5d96520..fcaaf664cbec 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c @@ -249,7 +249,7 @@ u32 RTL8821AE_PHY_REG_ARRAY[] = { 0x824, 0x00030FE0, 0x828, 0x00000000, 0x82C, 0x002081DD, - 0x830, 0x2AAA8E24, + 0x830, 0x2AAAEEC8, 0x834, 0x0037A706, 0x838, 0x06489B44, 0x83C, 0x0000095B, @@ -324,10 +324,10 @@ u32 RTL8821AE_PHY_REG_ARRAY[] = { 0x9D8, 0x00000000, 0x9DC, 0x00000000, 0x9E0, 0x00005D00, - 0x9E4, 0x00000002, + 0x9E4, 0x00000003, 0x9E8, 0x00000001, 0xA00, 0x00D047C8, - 0xA04, 0x01FF000C, + 0xA04, 0x01FF800C, 0xA08, 0x8C8A8300, 0xA0C, 0x2E68000F, 0xA10, 0x9500BB78, @@ -1320,7 +1320,11 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x083, 0x00021800, 0x084, 0x00028000, 0x085, 0x00048000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x0009483A, + 0xA0000000, 0x00000000, 0x086, 0x00094838, + 0xB0000000, 0x00000000, 0x087, 0x00044980, 0x088, 0x00048000, 0x089, 0x0000D480, @@ -1409,26 +1413,32 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x03C, 0x000CA000, 0x0EF, 0x00000000, 0x0EF, 0x00001100, - 0xFF0F0104, 0xABCD, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0004ADF3, 0x034, 0x00049DF0, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0004ADF3, 0x034, 0x00049DF0, - 0xFF0F0404, 0xCDEF, - 0x034, 0x0004ADF3, - 0x034, 0x00049DF0, - 0xFF0F0200, 0xCDEF, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0004ADF5, 0x034, 0x00049DF2, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0004A0F3, 0x034, 0x000490B1, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0004A0F3, + 0x034, 0x000490B1, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0004ADF5, + 0x034, 0x00049DF2, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0004ADF3, + 0x034, 0x00049DF0, + 0xA0000000, 0x00000000, 0x034, 0x0004ADF7, 0x034, 0x00049DF3, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00048DED, 0x034, 0x00047DEA, 0x034, 0x00046DE7, @@ -1438,7 +1448,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00042886, 0x034, 0x00041486, 0x034, 0x00040447, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00048DED, 0x034, 0x00047DEA, 0x034, 0x00046DE7, @@ -1448,17 +1458,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00042886, 0x034, 0x00041486, 0x034, 0x00040447, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00048DED, - 0x034, 0x00047DEA, - 0x034, 0x00046DE7, - 0x034, 0x00045CE9, - 0x034, 0x00044CE6, - 0x034, 0x000438C6, - 0x034, 0x00042886, - 0x034, 0x00041486, - 0x034, 0x00040447, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x000480AE, 0x034, 0x000470AB, 0x034, 0x0004608B, @@ -1468,7 +1468,27 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00042026, 0x034, 0x00041023, 0x034, 0x00040002, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x000480AE, + 0x034, 0x000470AB, + 0x034, 0x0004608B, + 0x034, 0x00045069, + 0x034, 0x00044048, + 0x034, 0x00043045, + 0x034, 0x00042026, + 0x034, 0x00041023, + 0x034, 0x00040002, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x00048DED, + 0x034, 0x00047DEA, + 0x034, 0x00046DE7, + 0x034, 0x00045CE9, + 0x034, 0x00044CE6, + 0x034, 0x000438C6, + 0x034, 0x00042886, + 0x034, 0x00041486, + 0x034, 0x00040447, + 0xA0000000, 0x00000000, 0x034, 0x00048DEF, 0x034, 0x00047DEC, 0x034, 0x00046DE9, @@ -1478,28 +1498,36 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x0004248A, 0x034, 0x0004108D, 0x034, 0x0004008A, - 0xFF0F0104, 0xDEAD, - 0xFF0F0200, 0xABCD, + 0xB0000000, 0x00000000, + 0x80000210, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0002ADF4, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0002A0F3, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0002A0F3, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0002ADF4, + 0xA0000000, 0x00000000, 0x034, 0x0002ADF7, - 0xFF0F0200, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00029DF4, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00029DF4, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00029DF4, - 0xFF0F0200, 0xCDEF, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00029DF1, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x000290F0, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x000290F0, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x00029DF1, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x00029DF4, + 0xA0000000, 0x00000000, 0x034, 0x00029DF2, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00028DF1, 0x034, 0x00027DEE, 0x034, 0x00026DEB, @@ -1509,7 +1537,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00022889, 0x034, 0x00021489, 0x034, 0x0002044A, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00028DF1, 0x034, 0x00027DEE, 0x034, 0x00026DEB, @@ -1519,17 +1547,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00022889, 0x034, 0x00021489, 0x034, 0x0002044A, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00028DF1, - 0x034, 0x00027DEE, - 0x034, 0x00026DEB, - 0x034, 0x00025CEC, - 0x034, 0x00024CE9, - 0x034, 0x000238CA, - 0x034, 0x00022889, - 0x034, 0x00021489, - 0x034, 0x0002044A, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x000280AF, 0x034, 0x000270AC, 0x034, 0x0002608B, @@ -1539,7 +1557,27 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00022026, 0x034, 0x00021023, 0x034, 0x00020002, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x000280AF, + 0x034, 0x000270AC, + 0x034, 0x0002608B, + 0x034, 0x00025069, + 0x034, 0x00024048, + 0x034, 0x00023045, + 0x034, 0x00022026, + 0x034, 0x00021023, + 0x034, 0x00020002, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x00028DF1, + 0x034, 0x00027DEE, + 0x034, 0x00026DEB, + 0x034, 0x00025CEC, + 0x034, 0x00024CE9, + 0x034, 0x000238CA, + 0x034, 0x00022889, + 0x034, 0x00021489, + 0x034, 0x0002044A, + 0xA0000000, 0x00000000, 0x034, 0x00028DEE, 0x034, 0x00027DEB, 0x034, 0x00026CCD, @@ -1549,19 +1587,24 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00022849, 0x034, 0x00021449, 0x034, 0x0002004D, - 0xFF0F0104, 0xDEAD, - 0xFF0F02C0, 0xABCD, + 0xB0000000, 0x00000000, + 0x8000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0000A0D7, 0x034, 0x000090D3, 0x034, 0x000080B1, 0x034, 0x000070AE, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0000A0D7, + 0x034, 0x000090D3, + 0x034, 0x000080B1, + 0x034, 0x000070AE, + 0xA0000000, 0x00000000, 0x034, 0x0000ADF7, 0x034, 0x00009DF4, 0x034, 0x00008DF1, 0x034, 0x00007DEE, - 0xFF0F02C0, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00006DEB, 0x034, 0x00005CEC, 0x034, 0x00004CE9, @@ -1569,7 +1612,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00002889, 0x034, 0x00001489, 0x034, 0x0000044A, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x00006DEB, 0x034, 0x00005CEC, 0x034, 0x00004CE9, @@ -1577,15 +1620,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00002889, 0x034, 0x00001489, 0x034, 0x0000044A, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00006DEB, - 0x034, 0x00005CEC, - 0x034, 0x00004CE9, - 0x034, 0x000038CA, - 0x034, 0x00002889, - 0x034, 0x00001489, - 0x034, 0x0000044A, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0000608D, 0x034, 0x0000506B, 0x034, 0x0000404A, @@ -1593,7 +1628,23 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00002044, 0x034, 0x00001025, 0x034, 0x00000004, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0000608D, + 0x034, 0x0000506B, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x00002044, + 0x034, 0x00001025, + 0x034, 0x00000004, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x00006DEB, + 0x034, 0x00005CEC, + 0x034, 0x00004CE9, + 0x034, 0x000038CA, + 0x034, 0x00002889, + 0x034, 0x00001489, + 0x034, 0x0000044A, + 0xA0000000, 0x00000000, 0x034, 0x00006DCD, 0x034, 0x00005CCD, 0x034, 0x00004CCA, @@ -1601,11 +1652,11 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x034, 0x00002888, 0x034, 0x00001488, 0x034, 0x00000486, - 0xFF0F0104, 0xDEAD, + 0xB0000000, 0x00000000, 0x0EF, 0x00000000, 0x018, 0x0001712A, 0x0EF, 0x00000040, - 0xFF0F0104, 0xABCD, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x035, 0x00000187, 0x035, 0x00008187, 0x035, 0x00010187, @@ -1615,7 +1666,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x035, 0x00040188, 0x035, 0x00048188, 0x035, 0x00050188, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x035, 0x00000187, 0x035, 0x00008187, 0x035, 0x00010187, @@ -1625,17 +1676,17 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x035, 0x00040188, 0x035, 0x00048188, 0x035, 0x00050188, - 0xFF0F0404, 0xCDEF, - 0x035, 0x00000187, - 0x035, 0x00008187, - 0x035, 0x00010187, - 0x035, 0x00020188, - 0x035, 0x00028188, - 0x035, 0x00030188, - 0x035, 0x00040188, - 0x035, 0x00048188, - 0x035, 0x00050188, - 0xCDCDCDCD, 0xCDCD, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, + 0x035, 0x00000128, + 0x035, 0x00008128, + 0x035, 0x00010128, + 0x035, 0x000201C8, + 0x035, 0x000281C8, + 0x035, 0x000301C8, + 0x035, 0x000401C8, + 0x035, 0x000481C8, + 0x035, 0x000501C8, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, 0x035, 0x00000145, 0x035, 0x00008145, 0x035, 0x00010145, @@ -1645,11 +1696,41 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x035, 0x000401C7, 0x035, 0x000481C7, 0x035, 0x000501C7, - 0xFF0F0104, 0xDEAD, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x035, 0x00000128, + 0x035, 0x00008128, + 0x035, 0x00010128, + 0x035, 0x000201C8, + 0x035, 0x000281C8, + 0x035, 0x000301C8, + 0x035, 0x000401C8, + 0x035, 0x000481C8, + 0x035, 0x000501C8, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x035, 0x00000187, + 0x035, 0x00008187, + 0x035, 0x00010187, + 0x035, 0x00020188, + 0x035, 0x00028188, + 0x035, 0x00030188, + 0x035, 0x00040188, + 0x035, 0x00048188, + 0x035, 0x00050188, + 0xA0000000, 0x00000000, + 0x035, 0x00000145, + 0x035, 0x00008145, + 0x035, 0x00010145, + 0x035, 0x00020196, + 0x035, 0x00028196, + 0x035, 0x00030196, + 0x035, 0x000401C7, + 0x035, 0x000481C7, + 0x035, 0x000501C7, + 0xB0000000, 0x00000000, 0x0EF, 0x00000000, 0x018, 0x0001712A, 0x0EF, 0x00000010, - 0xFF0F0104, 0xABCD, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x036, 0x00085733, 0x036, 0x0008D733, 0x036, 0x00095733, @@ -1662,7 +1743,7 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x036, 0x000CE4B4, 0x036, 0x000D64B4, 0x036, 0x000DE4B4, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x036, 0x00085733, 0x036, 0x0008D733, 0x036, 0x00095733, @@ -1675,20 +1756,20 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x036, 0x000CE4B4, 0x036, 0x000D64B4, 0x036, 0x000DE4B4, - 0xFF0F0404, 0xCDEF, - 0x036, 0x00085733, - 0x036, 0x0008D733, - 0x036, 0x00095733, - 0x036, 0x0009D733, - 0x036, 0x000A64B4, - 0x036, 0x000AE4B4, - 0x036, 0x000B64B4, - 0x036, 0x000BE4B4, - 0x036, 0x000C64B4, - 0x036, 0x000CE4B4, - 0x036, 0x000D64B4, - 0x036, 0x000DE4B4, - 0xCDCDCDCD, 0xCDCD, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, + 0x036, 0x000063B5, + 0x036, 0x0000E3B5, + 0x036, 0x000163B5, + 0x036, 0x0001E3B5, + 0x036, 0x000263B5, + 0x036, 0x0002E3B5, + 0x036, 0x000363B5, + 0x036, 0x0003E3B5, + 0x036, 0x000463B5, + 0x036, 0x0004E3B5, + 0x036, 0x000563B5, + 0x036, 0x0005E3B5, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, 0x036, 0x000056B3, 0x036, 0x0000D6B3, 0x036, 0x000156B3, @@ -1701,103 +1782,201 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x036, 0x0004E7B4, 0x036, 0x000567B4, 0x036, 0x0005E7B4, - 0xFF0F0104, 0xDEAD, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x036, 0x000063B5, + 0x036, 0x0000E3B5, + 0x036, 0x000163B5, + 0x036, 0x0001E3B5, + 0x036, 0x000263B5, + 0x036, 0x0002E3B5, + 0x036, 0x000363B5, + 0x036, 0x0003E3B5, + 0x036, 0x000463B5, + 0x036, 0x0004E3B5, + 0x036, 0x000563B5, + 0x036, 0x0005E3B5, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x036, 0x00085733, + 0x036, 0x0008D733, + 0x036, 0x00095733, + 0x036, 0x0009D733, + 0x036, 0x000A64B4, + 0x036, 0x000AE4B4, + 0x036, 0x000B64B4, + 0x036, 0x000BE4B4, + 0x036, 0x000C64B4, + 0x036, 0x000CE4B4, + 0x036, 0x000D64B4, + 0x036, 0x000DE4B4, + 0xA0000000, 0x00000000, + 0x036, 0x000056B3, + 0x036, 0x0000D6B3, + 0x036, 0x000156B3, + 0x036, 0x0001D6B3, + 0x036, 0x00026634, + 0x036, 0x0002E634, + 0x036, 0x00036634, + 0x036, 0x0003E634, + 0x036, 0x000467B4, + 0x036, 0x0004E7B4, + 0x036, 0x000567B4, + 0x036, 0x0005E7B4, + 0xB0000000, 0x00000000, 0x0EF, 0x00000000, 0x0EF, 0x00000008, - 0xFF0F0104, 0xABCD, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x000001C8, 0x03C, 0x00000492, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x000001C8, 0x03C, 0x00000492, - 0xFF0F0404, 0xCDEF, - 0x03C, 0x000001C8, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, + 0x03C, 0x000001B6, 0x03C, 0x00000492, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x0000022A, 0x03C, 0x00000594, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x03C, 0x000001B6, + 0x03C, 0x00000492, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x03C, 0x000001C8, + 0x03C, 0x00000492, + 0xA0000000, 0x00000000, + 0x03C, 0x0000022A, + 0x03C, 0x00000594, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x00000800, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x00000800, - 0xFF0F0404, 0xCDEF, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x00000800, - 0xFF0F02C0, 0xCDEF, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x03C, 0x00000820, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x03C, 0x00000820, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x03C, 0x00000800, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x03C, 0x00000800, + 0xA0000000, 0x00000000, 0x03C, 0x00000900, - 0xFF0F0104, 0xDEAD, + 0xB0000000, 0x00000000, 0x0EF, 0x00000000, 0x018, 0x0001712A, 0x0EF, 0x00000002, - 0xFF0F0104, 0xABCD, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x008, 0x0004E400, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x008, 0x0004E400, - 0xFF0F0404, 0xCDEF, - 0x008, 0x0004E400, - 0xCDCDCDCD, 0xCDCD, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, 0x008, 0x00002000, - 0xFF0F0104, 0xDEAD, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, + 0x008, 0x00002000, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x008, 0x00002000, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x008, 0x00002000, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x008, 0x0004E400, + 0xA0000000, 0x00000000, + 0x008, 0x00002000, + 0xB0000000, 0x00000000, 0x0EF, 0x00000000, 0x0DF, 0x000000C0, - 0x01F, 0x00040064, - 0xFF0F0104, 0xABCD, + 0x01F, 0x00000064, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x058, 0x000A7284, 0x059, 0x000600EC, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x058, 0x000A7284, 0x059, 0x000600EC, - 0xFF0F0404, 0xCDEF, - 0x058, 0x000A7284, - 0x059, 0x000600EC, - 0xCDCDCDCD, 0xCDCD, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x058, 0x00081184, 0x059, 0x0006016C, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x058, 0x00081184, + 0x059, 0x0006016C, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x058, 0x00081184, + 0x059, 0x0006016C, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x058, 0x000A7284, + 0x059, 0x000600EC, + 0xA0000000, 0x00000000, + 0x058, 0x00081184, + 0x059, 0x0006016C, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x061, 0x000E8D73, 0x062, 0x00093FC5, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x061, 0x000E8D73, 0x062, 0x00093FC5, - 0xFF0F0404, 0xCDEF, - 0x061, 0x000E8D73, - 0x062, 0x00093FC5, - 0xCDCDCDCD, 0xCDCD, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x000EFD83, + 0x062, 0x00093FCC, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, 0x061, 0x000EAD53, 0x062, 0x00093BC4, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x000EFD83, + 0x062, 0x00093FCC, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x000E8D73, + 0x062, 0x00093FC5, + 0xA0000000, 0x00000000, + 0x061, 0x000EAD53, + 0x062, 0x00093BC4, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x063, 0x000110E9, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x063, 0x000110E9, - 0xFF0F0404, 0xCDEF, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x000110EB, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, 0x063, 0x000110E9, - 0xFF0F0200, 0xCDEF, - 0x063, 0x000710E9, - 0xFF0F02C0, 0xCDEF, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, 0x063, 0x000110E9, - 0xCDCDCDCD, 0xCDCD, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x000110EB, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x000110E9, + 0xA0000000, 0x00000000, 0x063, 0x000714E9, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x064, 0x0001C27C, - 0xFF0F0204, 0xCDEF, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, 0x064, 0x0001C27C, - 0xFF0F0404, 0xCDEF, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, 0x064, 0x0001C27C, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, 0x064, 0x0001C67C, - 0xFF0F0104, 0xDEAD, - 0xFF0F0200, 0xABCD, - 0x065, 0x00093016, - 0xFF0F02C0, 0xCDEF, - 0x065, 0x00093015, - 0xCDCDCDCD, 0xCDCD, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x064, 0x0001C27C, + 0x90000410, 0x00000000, 0x40000000, 0x00000000, + 0x064, 0x0001C27C, + 0xA0000000, 0x00000000, + 0x064, 0x0001C67C, + 0xB0000000, 0x00000000, + 0x80000111, 0x00000000, 0x40000000, 0x00000000, 0x065, 0x00091016, - 0xFF0F0200, 0xDEAD, + 0x90000110, 0x00000000, 0x40000000, 0x00000000, + 0x065, 0x00091016, + 0x90000210, 0x00000000, 0x40000000, 0x00000000, + 0x065, 0x00093016, + 0x9000020c, 0x00000000, 0x40000000, 0x00000000, + 0x065, 0x00093015, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x065, 0x00093015, + 0x90000200, 0x00000000, 0x40000000, 0x00000000, + 0x065, 0x00093016, + 0xA0000000, 0x00000000, + 0x065, 0x00091016, + 0xB0000000, 0x00000000, 0x018, 0x00000006, 0x0EF, 0x00002000, 0x03B, 0x0003824B, @@ -1895,9 +2074,10 @@ u32 RTL8821AE_RADIOA_ARRAY[] = { 0x0B4, 0x0001214C, 0x0B7, 0x0003000C, 0x01C, 0x000539D2, + 0x0C4, 0x000AFE00, 0x018, 0x0001F12A, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, 0x018, 0x0001712A, }; @@ -2017,6 +2197,7 @@ u32 RTL8812AE_MAC_REG_ARRAY[] = { u32 RTL8812AE_MAC_1T_ARRAYLEN = ARRAY_SIZE(RTL8812AE_MAC_REG_ARRAY); u32 RTL8821AE_MAC_REG_ARRAY[] = { + 0x421, 0x0000000F, 0x428, 0x0000000A, 0x429, 0x00000010, 0x430, 0x00000000, @@ -2485,7 +2666,7 @@ u32 RTL8821AE_AGC_TAB_ARRAY[] = { 0x81C, 0xA6360001, 0x81C, 0xA5380001, 0x81C, 0xA43A0001, - 0x81C, 0xA33C0001, + 0x81C, 0x683C0001, 0x81C, 0x673E0001, 0x81C, 0x66400001, 0x81C, 0x65420001, @@ -2519,7 +2700,7 @@ u32 RTL8821AE_AGC_TAB_ARRAY[] = { 0x81C, 0x017A0001, 0x81C, 0x017C0001, 0x81C, 0x017E0001, - 0xFF0F02C0, 0xABCD, + 0x8000020c, 0x00000000, 0x40000000, 0x00000000, 0x81C, 0xFB000101, 0x81C, 0xFA020101, 0x81C, 0xF9040101, @@ -2578,7 +2759,66 @@ u32 RTL8821AE_AGC_TAB_ARRAY[] = { 0x81C, 0x016E0101, 0x81C, 0x01700101, 0x81C, 0x01720101, - 0xCDCDCDCD, 0xCDCD, + 0x9000040c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000101, + 0x81C, 0xFA020101, + 0x81C, 0xF9040101, + 0x81C, 0xF8060101, + 0x81C, 0xF7080101, + 0x81C, 0xF60A0101, + 0x81C, 0xF50C0101, + 0x81C, 0xF40E0101, + 0x81C, 0xF3100101, + 0x81C, 0xF2120101, + 0x81C, 0xF1140101, + 0x81C, 0xF0160101, + 0x81C, 0xEF180101, + 0x81C, 0xEE1A0101, + 0x81C, 0xED1C0101, + 0x81C, 0xEC1E0101, + 0x81C, 0xEB200101, + 0x81C, 0xEA220101, + 0x81C, 0xE9240101, + 0x81C, 0xE8260101, + 0x81C, 0xE7280101, + 0x81C, 0xE62A0101, + 0x81C, 0xE52C0101, + 0x81C, 0xE42E0101, + 0x81C, 0xE3300101, + 0x81C, 0xA5320101, + 0x81C, 0xA4340101, + 0x81C, 0xA3360101, + 0x81C, 0x87380101, + 0x81C, 0x863A0101, + 0x81C, 0x853C0101, + 0x81C, 0x843E0101, + 0x81C, 0x69400101, + 0x81C, 0x68420101, + 0x81C, 0x67440101, + 0x81C, 0x66460101, + 0x81C, 0x49480101, + 0x81C, 0x484A0101, + 0x81C, 0x474C0101, + 0x81C, 0x2A4E0101, + 0x81C, 0x29500101, + 0x81C, 0x28520101, + 0x81C, 0x27540101, + 0x81C, 0x26560101, + 0x81C, 0x25580101, + 0x81C, 0x245A0101, + 0x81C, 0x235C0101, + 0x81C, 0x055E0101, + 0x81C, 0x04600101, + 0x81C, 0x03620101, + 0x81C, 0x02640101, + 0x81C, 0x01660101, + 0x81C, 0x01680101, + 0x81C, 0x016A0101, + 0x81C, 0x016C0101, + 0x81C, 0x016E0101, + 0x81C, 0x01700101, + 0x81C, 0x01720101, + 0xA0000000, 0x00000000, 0x81C, 0xFF000101, 0x81C, 0xFF020101, 0x81C, 0xFE040101, @@ -2637,7 +2877,7 @@ u32 RTL8821AE_AGC_TAB_ARRAY[] = { 0x81C, 0x046E0101, 0x81C, 0x03700101, 0x81C, 0x02720101, - 0xFF0F02C0, 0xDEAD, + 0xB0000000, 0x00000000, 0x81C, 0x01740101, 0x81C, 0x01760101, 0x81C, 0x01780101, From a221d0afbf39fcaadd481acf3551cd7269b647c2 Mon Sep 17 00:00:00 2001 From: wengjianfeng Date: Tue, 23 Feb 2021 14:57:54 +0800 Subject: [PATCH 152/188] qtnfmac: remove meaningless labels some function's label meaningless, the return statement follows the goto statement, so just remove it. Signed-off-by: wengjianfeng Reviewed-by: Sergey Matyukevich Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210223065754.34392-1-samirweng1979@163.com --- .../net/wireless/quantenna/qtnfmac/cfg80211.c | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 504b4d0b98c4..84b15a655eab 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -680,13 +680,10 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, eth_zero_addr(vif->bssid); ret = qtnf_cmd_send_connect(vif, sme); - if (ret) { + if (ret) pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid, vif->vifid); - goto out; - } -out: return ret; } @@ -702,13 +699,10 @@ qtnf_external_auth(struct wiphy *wiphy, struct net_device *dev, pr_warn("unexpected bssid: %pM", auth->bssid); ret = qtnf_cmd_send_external_auth(vif, auth); - if (ret) { + if (ret) pr_err("VIF%u.%u: failed to report external auth\n", vif->mac->macid, vif->vifid); - goto out; - } -out: return ret; } @@ -727,8 +721,7 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev, } if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { - ret = -EOPNOTSUPP; - goto out; + return -EOPNOTSUPP; } ret = qtnf_cmd_send_disconnect(vif, reason_code); @@ -742,7 +735,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev, NULL, 0, true, GFP_KERNEL); } -out: return ret; } @@ -935,13 +927,10 @@ static int qtnf_update_owe_info(struct wiphy *wiphy, struct net_device *dev, return -EOPNOTSUPP; ret = qtnf_cmd_send_update_owe(vif, owe_info); - if (ret) { + if (ret) pr_err("VIF%u.%u: failed to update owe info\n", vif->mac->macid, vif->vifid); - goto out; - } -out: return ret; } @@ -987,18 +976,14 @@ static int qtnf_resume(struct wiphy *wiphy) vif = qtnf_mac_get_base_vif(mac); if (!vif) { pr_err("MAC%u: primary VIF is not configured\n", mac->macid); - ret = -EFAULT; - goto exit; + return -EFAULT; } ret = qtnf_cmd_send_wowlan_set(vif, NULL); - if (ret) { + if (ret) pr_err("MAC%u: failed to reset WoWLAN triggers\n", mac->macid); - goto exit; - } -exit: return ret; } From 2377b1c49d4831c09af269cdbe21791e8945cf97 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Sun, 21 Mar 2021 01:14:26 +0530 Subject: [PATCH 153/188] rtlwifi: Few mundane typo fixes s/resovle/resolve/ s/broadcase/broadcast/ s/sytem/system/ Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210320194426.21621-1-unixbhaskar@gmail.com --- drivers/net/wireless/realtek/rtlwifi/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 965bd9589045..c9b6ee81dcb9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -564,7 +564,7 @@ static int rtl_op_resume(struct ieee80211_hw *hw) rtlhal->enter_pnp_sleep = false; rtlhal->wake_from_pnp_sleep = true; - /* to resovle s4 can not wake up*/ + /* to resolve s4 can not wake up*/ now = ktime_get_real_seconds(); if (now - rtlhal->last_suspend_sec < 5) return -1; @@ -806,7 +806,7 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, if (0 == changed_flags) return; - /*TODO: we disable broadcase now, so enable here */ + /*TODO: we disable broadcast now, so enable here */ if (changed_flags & FIF_ALLMULTI) { if (*new_flags & FIF_ALLMULTI) { mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | @@ -1796,7 +1796,7 @@ bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, value |= (GET_PWR_CFG_VALUE(cfg_cmd) & GET_PWR_CFG_MASK(cfg_cmd)); - /*Write the value back to sytem register*/ + /*Write the value back to system register*/ rtl_write_byte(rtlpriv, offset, value); break; case PWR_CMD_POLLING: From 87431bc1f0f67aa2d23ca1b9682fe54f68549d42 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 27 Mar 2021 23:00:14 +0000 Subject: [PATCH 154/188] rtlwifi: remove redundant assignment to variable err Variable err is assigned -ENODEV followed by an error return path via label error_out that does not access the variable and returns with the -ENODEV error return code. The assignment to err is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210327230014.25554-1-colin.king@canonical.com --- drivers/net/wireless/realtek/rtlwifi/usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 6c5e242b1bc5..37a9a03123f3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -1070,7 +1070,6 @@ int rtl_usb_probe(struct usb_interface *intf, err = ieee80211_register_hw(hw); if (err) { pr_err("Can't register mac80211 hw.\n"); - err = -ENODEV; goto error_out; } rtlpriv->mac80211.mac80211_registered = 1; From 8e04a06530c613b6a4c7806c1078d8305a788086 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 31 Mar 2021 17:13:43 +0800 Subject: [PATCH 155/188] rtlwifi: rtl8188ee: remove redundant assignment of variable rtlpriv->btcoexist.reg_bt_sco Assigning value "3" to "rtlpriv->btcoexist.reg_bt_sco" here, but that stored value is overwritten before it can be used. Coverity reports this problem as CWE563: A value assigned to a variable is never used. drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c: rtl8188ee_bt_reg_init Reported-by: Abaci Robot Signed-off-by: Yang Li Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1617182023-110950-1-git-send-email-yang.lee@linux.alibaba.com --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c index 861cc663ca93..bf686a916acb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c @@ -2466,8 +2466,6 @@ void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw) /* 0:Low, 1:High, 2:From Efuse. */ rtlpriv->btcoexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpriv->btcoexist.reg_bt_sco = 3; /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ rtlpriv->btcoexist.reg_bt_sco = 0; } From 987e9bcdd0b76a9d35f0b82013294429b401f7bb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 2 Apr 2021 19:09:35 +0200 Subject: [PATCH 156/188] rtlwifi: remove rtl_get_tid_h 'rtl_get_tid_h()' is the same as 'ieee80211_get_tid()'. So this function can be removed to save a line of code. Signed-off-by: Christophe JAILLET Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/db340a67a95c119e4f9ba8fa99aea1c73d0dcfc9.1617383263.git.christophe.jaillet@wanadoo.fr --- drivers/net/wireless/realtek/rtlwifi/wifi.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index fdccfd29fd61..9119144bb5a3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -3086,14 +3086,9 @@ static inline __le16 rtl_get_fc(struct sk_buff *skb) return rtl_get_hdr(skb)->frame_control; } -static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) -{ - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -} - static inline u16 rtl_get_tid(struct sk_buff *skb) { - return rtl_get_tid_h(rtl_get_hdr(skb)); + return ieee80211_get_tid(rtl_get_hdr(skb)); } static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, From 1186006adee97ebb5b16db0e4ae64e8efb2c8f76 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 5 Apr 2021 09:57:14 +0200 Subject: [PATCH 157/188] rtlwifi: Simplify locking of a skb list accesses The 'c2hcmd_lock' spinlock is only used to protect some __skb_queue_tail() and __skb_dequeue() calls. Use the lock provided in the skb itself and call skb_queue_tail() and skb_dequeue(). These functions already include the correct locking. Signed-off-by: Christophe JAILLET Acked-by: Larry Finger Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/99cf8894fd52202cb7ce2ec6e3200eef400bc071.1617609346.git.christophe.jaillet@wanadoo.fr --- drivers/net/wireless/realtek/rtlwifi/base.c | 15 ++------------- drivers/net/wireless/realtek/rtlwifi/wifi.h | 1 - 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 6e8bd99e8911..2a7ee90a3f54 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -551,7 +551,6 @@ int rtl_init_core(struct ieee80211_hw *hw) spin_lock_init(&rtlpriv->locks.rf_lock); spin_lock_init(&rtlpriv->locks.waitq_lock); spin_lock_init(&rtlpriv->locks.entry_list_lock); - spin_lock_init(&rtlpriv->locks.c2hcmd_lock); spin_lock_init(&rtlpriv->locks.scan_list_lock); spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); spin_lock_init(&rtlpriv->locks.fw_ps_lock); @@ -2269,7 +2268,6 @@ static bool rtl_c2h_fast_cmd(struct ieee80211_hw *hw, struct sk_buff *skb) void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned long flags; if (rtl_c2h_fast_cmd(hw, skb)) { rtl_c2h_content_parsing(hw, skb); @@ -2278,11 +2276,7 @@ void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb) } /* enqueue */ - spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags); - - __skb_queue_tail(&rtlpriv->c2hcmd_queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags); + skb_queue_tail(&rtlpriv->c2hcmd_queue, skb); /* wake up wq */ queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.c2hcmd_wq, 0); @@ -2340,16 +2334,11 @@ void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct sk_buff *skb; - unsigned long flags; int i; for (i = 0; i < 200; i++) { /* dequeue a task */ - spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags); - - skb = __skb_dequeue(&rtlpriv->c2hcmd_queue); - - spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags); + skb = skb_dequeue(&rtlpriv->c2hcmd_queue); /* do it */ if (!skb) diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 9119144bb5a3..877ed6a1589f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2450,7 +2450,6 @@ struct rtl_locks { spinlock_t waitq_lock; spinlock_t entry_list_lock; spinlock_t usb_lock; - spinlock_t c2hcmd_lock; spinlock_t scan_list_lock; /* lock for the scan list */ /*FW clock change */ From fb98734f79365d5aa0737a6fec0a8c84c05c8eaa Mon Sep 17 00:00:00 2001 From: wengjianfeng Date: Tue, 6 Apr 2021 10:52:06 +0800 Subject: [PATCH 158/188] qtnfmac: remove meaningless goto statement and labels some function's label meaningless, the label statement follows the goto statement, no other statements, so just remove it. Reported-by: kernel test robot Signed-off-by: wengjianfeng Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210406025206.4924-1-samirweng1979@163.com --- .../net/wireless/quantenna/qtnfmac/commands.c | 67 ------------------- 1 file changed, 67 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index f3ccbd2b1084..c68563c83098 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -379,10 +379,6 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif) qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -407,10 +403,7 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg) cmd->do_register = reg; ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -446,10 +439,7 @@ int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, qtnf_cmd_skb_put_buffer(cmd_skb, buf, len); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -477,10 +467,6 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -1677,10 +1663,7 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) wiphy->retry_short); ret = qtnf_cmd_send(mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(mac->bus); return ret; @@ -1772,10 +1755,7 @@ int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise, params->seq_len); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -1807,10 +1787,7 @@ int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise, cmd->pairwise = pairwise; ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -1837,10 +1814,7 @@ int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index, cmd->multicast = multicast; ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -1864,10 +1838,7 @@ int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index) cmd->key_index = key_index; ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -1931,8 +1902,6 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac, } ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; out: qtnf_bus_unlock(vif->mac->bus); @@ -1966,10 +1935,7 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif, cmd->reason_code = cpu_to_le16(params->reason_code); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -2189,10 +2155,6 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -2218,10 +2180,6 @@ int qtnf_cmd_send_external_auth(struct qtnf_vif *vif, qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -2245,10 +2203,7 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code) cmd->reason = cpu_to_le16(reason_code); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -2271,10 +2226,6 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up) qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(vif->mac->bus); return ret; @@ -2580,10 +2531,6 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif, qtnf_bus_lock(bus); ret = qtnf_cmd_send(bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(bus); return ret; @@ -2611,10 +2558,6 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif, qtnf_bus_lock(bus); ret = qtnf_cmd_send(bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(bus); return ret; @@ -2639,10 +2582,7 @@ int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout) qtnf_bus_lock(bus); ret = qtnf_cmd_send(bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(bus); return ret; @@ -2754,10 +2694,7 @@ int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif, cmd->triggers = cpu_to_le32(triggers); ret = qtnf_cmd_send(bus, cmd_skb); - if (ret) - goto out; -out: qtnf_bus_unlock(bus); return ret; } @@ -2821,10 +2758,6 @@ int qtnf_cmd_send_update_owe(struct qtnf_vif *vif, qtnf_bus_lock(vif->mac->bus); ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(vif->mac->bus); return ret; From e9642be26a372013e47801e1dd98e8f4dcf78f50 Mon Sep 17 00:00:00 2001 From: Guobin Huang Date: Tue, 6 Apr 2021 20:16:46 +0800 Subject: [PATCH 159/188] rtlwifi: rtl8192de: Use DEFINE_SPINLOCK() for spinlock spinlock can be initialized automatically with DEFINE_SPINLOCK() rather than explicitly calling spin_lock_init(). Reported-by: Hulk Robot Signed-off-by: Guobin Huang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1617711406-49649-1-git-send-email-huangguobin4@huawei.com --- drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index 1dbdddce0823..a74724c971b9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -372,18 +372,14 @@ static struct pci_driver rtl92de_driver = { /* add global spin lock to solve the problem that * Dul mac register operation on the same time */ -spinlock_t globalmutex_power; -spinlock_t globalmutex_for_fwdownload; -spinlock_t globalmutex_for_power_and_efuse; +DEFINE_SPINLOCK(globalmutex_power); +DEFINE_SPINLOCK(globalmutex_for_fwdownload); +DEFINE_SPINLOCK(globalmutex_for_power_and_efuse); static int __init rtl92de_module_init(void) { int ret = 0; - spin_lock_init(&globalmutex_power); - spin_lock_init(&globalmutex_for_fwdownload); - spin_lock_init(&globalmutex_for_power_and_efuse); - ret = pci_register_driver(&rtl92de_driver); if (ret) WARN_ONCE(true, "rtl8192de: No device found\n"); From 260a9ad9446723d4063ed802989758852809714d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 14 Apr 2021 11:29:55 +0300 Subject: [PATCH 160/188] ipw2x00: potential buffer overflow in libipw_wx_set_encodeext() The "ext->key_len" is a u16 that comes from the user. If it's over SCM_KEY_LEN (32) that could lead to memory corruption. Fixes: e0d369d1d969 ("[PATCH] ieee82011: Added WE-18 support to default wireless extension handler") Cc: stable@vger.kernel.org Signed-off-by: Dan Carpenter Acked-by: Stanislav Yakovlev Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/YHaoA1i+8uT4ir4h@mwanda --- drivers/net/wireless/intel/ipw2x00/libipw_wx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_wx.c b/drivers/net/wireless/intel/ipw2x00/libipw_wx.c index a0cf78c418ac..903de34028ef 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_wx.c @@ -633,8 +633,10 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, } if (ext->alg != IW_ENCODE_ALG_NONE) { - memcpy(sec.keys[idx], ext->key, ext->key_len); - sec.key_sizes[idx] = ext->key_len; + int key_len = clamp_val(ext->key_len, 0, SCM_KEY_LEN); + + memcpy(sec.keys[idx], ext->key, key_len); + sec.key_sizes[idx] = key_len; sec.flags |= (1 << idx); if (ext->alg == IW_ENCODE_ALG_WEP) { sec.encode_alg[idx] = SEC_ALG_WEP; From d23a962203531ab281f233fa6140cf66ed4fb69f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 24 Feb 2021 18:44:54 -0800 Subject: [PATCH 161/188] mwifiex: don't print SSID to logs There are a few reasons not to dump SSIDs as-is in kernel logs: 1) they're not guaranteed to be any particular text encoding (UTF-8, ASCII, ...) in general 2) it's somewhat redundant; the BSSID should be enough to uniquely identify the AP/STA to which we're connecting 3) BSSIDs have an easily-recognized format, whereas SSIDs do not (they are free-form) 4) other common drivers (e.g., everything based on mac80211) get along just fine by only including BSSIDs when logging state transitions Additional notes on reason #3: this is important for the privacy-conscious, especially when providing tools that convey kernel logs on behalf of a user -- e.g., when reporting bugs. So for example, it's easy to automatically filter logs for MAC addresses, but it's much harder to filter SSIDs out of unstructured text. Signed-off-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210225024454.4106485-1-briannorris@chromium.org --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index a2ed268ce0da..0961f4a5e415 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -2300,8 +2300,7 @@ done: is_scanning_required = 1; } else { mwifiex_dbg(priv->adapter, MSG, - "info: trying to associate to '%.*s' bssid %pM\n", - req_ssid.ssid_len, (char *)req_ssid.ssid, + "info: trying to associate to bssid %pM\n", bss->bssid); memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); break; @@ -2378,8 +2377,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } mwifiex_dbg(adapter, INFO, - "info: Trying to associate to %.*s and bssid %pM\n", - (int)sme->ssid_len, (char *)sme->ssid, sme->bssid); + "info: Trying to associate to bssid %pM\n", sme->bssid); if (!mwifiex_stop_bg_scan(priv)) cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); @@ -2512,9 +2510,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, goto done; } - mwifiex_dbg(priv->adapter, MSG, - "info: trying to join to %.*s and bssid %pM\n", - params->ssid_len, (char *)params->ssid, params->bssid); + mwifiex_dbg(priv->adapter, MSG, "info: trying to join to bssid %pM\n", + params->bssid); mwifiex_set_ibss_params(priv, params); From f2131fa516b883841a593fc877dede57edd1ab0e Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Sat, 27 Feb 2021 17:29:14 +0000 Subject: [PATCH 162/188] wilc1000: Make SPI transfers work at 48MHz For CMD_SINGLE_READ and CMD_INTERNAL_READ, WILC may insert one or more zero bytes between the command response and the DATA Start tag (0xf3). This behavior appears to be undocumented in "ATWILC1000 USER GUIDE" (https://tinyurl.com/4hhshdts) but we have observed 1-4 zero bytes when the SPI bus operates at 48MHz and none when it operates at 1MHz. This code is derived from the equivalent code of the wilc driver in the linux-at91 repository. Signed-off-by: David Mosberger-Tang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210227172818.1711071-1-davidm@egauge.net --- drivers/net/wireless/microchip/wilc1000/spi.c | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index be732929322c..d11e365eeee2 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -11,6 +11,16 @@ #include "netdev.h" #include "cfg80211.h" +/* + * For CMD_SINGLE_READ and CMD_INTERNAL_READ, WILC may insert one or + * more zero bytes between the command response and the DATA Start tag + * (0xf3). This behavior appears to be undocumented in "ATWILC1000 + * USER GUIDE" (https://tinyurl.com/4hhshdts) but we have observed 1-4 + * zero bytes when the SPI bus operates at 48MHz and none when it + * operates at 1MHz. + */ +#define WILC_SPI_RSP_HDR_EXTRA_DATA 8 + struct wilc_spi { int crc_off; }; @@ -79,16 +89,15 @@ struct wilc_spi_cmd { } __packed; struct wilc_spi_read_rsp_data { - u8 rsp_cmd_type; - u8 status; - u8 resp_header; - u8 resp_data[4]; + u8 header; + u8 data[4]; u8 crc[]; } __packed; struct wilc_spi_rsp_data { u8 rsp_cmd_type; u8 status; + u8 data[]; } __packed; static int wilc_bus_probe(struct spi_device *spi) @@ -359,10 +368,11 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, struct spi_device *spi = to_spi_device(wilc->dev); struct wilc_spi *spi_priv = wilc->bus_data; u8 wb[32], rb[32]; - int cmd_len, resp_len; u8 crc[2]; + int cmd_len, resp_len, i; struct wilc_spi_cmd *c; - struct wilc_spi_read_rsp_data *r; + struct wilc_spi_read_rsp_data *r_data; + struct wilc_spi_rsp_data *r; memset(wb, 0x0, sizeof(wb)); memset(rb, 0x0, sizeof(rb)); @@ -384,7 +394,8 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, } cmd_len = offsetof(struct wilc_spi_cmd, u.simple_cmd.crc); - resp_len = sizeof(*r); + resp_len = sizeof(*r) + sizeof(*r_data) + WILC_SPI_RSP_HDR_EXTRA_DATA; + if (!spi_priv->crc_off) { c->u.simple_cmd.crc[0] = wilc_get_crc7(wb, cmd_len); cmd_len += 1; @@ -403,7 +414,7 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, return -EINVAL; } - r = (struct wilc_spi_read_rsp_data *)&rb[cmd_len]; + r = (struct wilc_spi_rsp_data *)&rb[cmd_len]; if (r->rsp_cmd_type != cmd) { dev_err(&spi->dev, "Failed cmd response, cmd (%02x), resp (%02x)\n", @@ -417,17 +428,22 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, return -EINVAL; } - if (WILC_GET_RESP_HDR_START(r->resp_header) != 0xf) { - dev_err(&spi->dev, "Error, data read response (%02x)\n", - r->resp_header); + for (i = 0; i < WILC_SPI_RSP_HDR_EXTRA_DATA; ++i) + if (WILC_GET_RESP_HDR_START(r->data[i]) == 0xf) + break; + + if (i >= WILC_SPI_RSP_HDR_EXTRA_DATA) { + dev_err(&spi->dev, "Error, data start missing\n"); return -EINVAL; } + r_data = (struct wilc_spi_read_rsp_data *)&r->data[i]; + if (b) - memcpy(b, r->resp_data, 4); + memcpy(b, r_data->data, 4); if (!spi_priv->crc_off) - memcpy(crc, r->crc, 2); + memcpy(crc, r_data->crc, 2); return 0; } From 5ee2d9dd73fc7b371d208bea0971f81585b5ad3d Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Sat, 27 Feb 2021 17:29:22 +0000 Subject: [PATCH 163/188] wilc1000: Introduce symbolic names for SPI protocol register The WILC1000 protocol control register has bits for enabling the CRCs (CRC7 for commands and CRC16 for data) and to set the data packet size. Define symbolic names for those so the code is more easily understood. Signed-off-by: David Mosberger-Tang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210227172818.1711071-2-davidm@egauge.net --- drivers/net/wireless/microchip/wilc1000/spi.c | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index d11e365eeee2..fca34d1999ec 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -46,12 +46,25 @@ static const struct wilc_hif_func wilc_hif_spi; #define CMD_RESET 0xcf #define SPI_ENABLE_VMM_RETRY_LIMIT 2 -#define DATA_PKT_SZ_256 256 -#define DATA_PKT_SZ_512 512 -#define DATA_PKT_SZ_1K 1024 -#define DATA_PKT_SZ_4K (4 * 1024) -#define DATA_PKT_SZ_8K (8 * 1024) -#define DATA_PKT_SZ DATA_PKT_SZ_8K + +#define PROTOCOL_REG_PKT_SZ_MASK GENMASK(6, 4) +#define PROTOCOL_REG_CRC16_MASK GENMASK(3, 3) +#define PROTOCOL_REG_CRC7_MASK GENMASK(2, 2) + +/* + * The SPI data packet size may be any integer power of two in the + * range from 256 to 8192 bytes. + */ +#define DATA_PKT_LOG_SZ_MIN 8 /* 256 B */ +#define DATA_PKT_LOG_SZ_MAX 13 /* 8 KiB */ + +/* + * Select the data packet size (log2 of number of bytes): Use the + * maximum data packet size. We only retransmit complete packets, so + * there is no benefit from using smaller data packets. + */ +#define DATA_PKT_LOG_SZ DATA_PKT_LOG_SZ_MAX +#define DATA_PKT_SZ (1 << DATA_PKT_LOG_SZ) #define USE_SPI_DMA 0 @@ -827,9 +840,16 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) } } if (spi_priv->crc_off == 0) { - reg &= ~0xc; /* disable crc checking */ - reg &= ~0x70; - reg |= (0x5 << 4); + /* disable crc checking: */ + reg &= ~(PROTOCOL_REG_CRC7_MASK | PROTOCOL_REG_CRC16_MASK); + + /* set the data packet size: */ + BUILD_BUG_ON(DATA_PKT_LOG_SZ < DATA_PKT_LOG_SZ_MIN + || DATA_PKT_LOG_SZ > DATA_PKT_LOG_SZ_MAX); + reg &= ~PROTOCOL_REG_PKT_SZ_MASK; + reg |= FIELD_PREP(PROTOCOL_REG_PKT_SZ_MASK, + DATA_PKT_LOG_SZ - DATA_PKT_LOG_SZ_MIN); + ret = spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg); if (ret) { dev_err(&spi->dev, From ce3b933832b6286d181c30f646449d6ccc2a2c8c Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Sat, 27 Feb 2021 17:29:46 +0000 Subject: [PATCH 164/188] wilc1000: Check for errors at end of DMA write After a DMA write to the WILC chip, check for and report any errors. This is based on code from the wilc driver in the linux-at91 repository. Signed-off-by: David Mosberger-Tang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210227172818.1711071-3-davidm@egauge.net --- drivers/net/wireless/microchip/wilc1000/spi.c | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index fca34d1999ec..0be93eabad69 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -47,6 +47,17 @@ static const struct wilc_hif_func wilc_hif_spi; #define SPI_ENABLE_VMM_RETRY_LIMIT 2 +/* SPI response fields (section 11.1.2 in ATWILC1000 User Guide): */ +#define RSP_START_FIELD GENMASK(7, 4) +#define RSP_TYPE_FIELD GENMASK(3, 0) + +/* SPI response values for the response fields: */ +#define RSP_START_TAG 0xc +#define RSP_TYPE_FIRST_PACKET 0x1 +#define RSP_TYPE_INNER_PACKET 0x2 +#define RSP_TYPE_LAST_PACKET 0x3 +#define RSP_STATE_NO_ERROR 0x00 + #define PROTOCOL_REG_PKT_SZ_MASK GENMASK(6, 4) #define PROTOCOL_REG_CRC16_MASK GENMASK(3, 3) #define PROTOCOL_REG_CRC7_MASK GENMASK(2, 2) @@ -750,6 +761,52 @@ static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) return 0; } +static int spi_data_rsp(struct wilc *wilc, u8 cmd) +{ + struct spi_device *spi = to_spi_device(wilc->dev); + int result, i; + u8 rsp[4]; + + /* + * The response to data packets is two bytes long. For + * efficiency's sake, wilc_spi_write() wisely ignores the + * responses for all packets but the final one. The downside + * of that optimization is that when the final data packet is + * short, we may receive (part of) the response to the + * second-to-last packet before the one for the final packet. + * To handle this, we always read 4 bytes and then search for + * the last byte that contains the "Response Start" code (0xc + * in the top 4 bits). We then know that this byte is the + * first response byte of the final data packet. + */ + result = wilc_spi_rx(wilc, rsp, sizeof(rsp)); + if (result) { + dev_err(&spi->dev, "Failed bus error...\n"); + return result; + } + + for (i = sizeof(rsp) - 2; i >= 0; --i) + if (FIELD_GET(RSP_START_FIELD, rsp[i]) == RSP_START_TAG) + break; + + if (i < 0) { + dev_err(&spi->dev, + "Data packet response missing (%02x %02x %02x %02x)\n", + rsp[0], rsp[1], rsp[2], rsp[3]); + return -1; + } + + /* rsp[i] is the last response start byte */ + + if (FIELD_GET(RSP_TYPE_FIELD, rsp[i]) != RSP_TYPE_LAST_PACKET + || rsp[i + 1] != RSP_STATE_NO_ERROR) { + dev_err(&spi->dev, "Data response error (%02x %02x)\n", + rsp[i], rsp[i + 1]); + return -1; + } + return 0; +} + static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct spi_device *spi = to_spi_device(wilc->dev); @@ -777,7 +834,10 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) return result; } - return 0; + /* + * Data response + */ + return spi_data_rsp(wilc, CMD_DMA_EXT_WRITE); } /******************************************** From c872e7ae056f16e27311fb30d637032cc3b1cb46 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Sat, 27 Feb 2021 17:31:38 +0000 Subject: [PATCH 165/188] wilc1000: Add support for enabling CRC The driver so far has always disabled CRC protection. This means any data corruption that occurrs during the SPI transfers could go undetected. This patch adds module parameters enable_crc7 and enable_crc16 to selectively turn on CRC7 (for command transfers) and CRC16 (for data transfers), respectively. The default configuration remains unchanged, with both CRC7 and CRC16 off. The performance impact of CRC was measured by running ttcp -t four times in a row on a SAMA5 device: CRC7 CRC16 Throughput: Standard deviation: ---- ----- ----------- ------------------- off off 1720 +/- 48 KB/s on off 1658 +/- 58 KB/s on on 1579 +/- 84 KB/s Signed-off-by: David Mosberger-Tang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210227172818.1711071-4-davidm@egauge.net --- .../net/wireless/microchip/wilc1000/Kconfig | 1 + drivers/net/wireless/microchip/wilc1000/spi.c | 178 +++++++++++------- 2 files changed, 115 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/Kconfig b/drivers/net/wireless/microchip/wilc1000/Kconfig index 7f15e42602dd..62cfcdc9aacc 100644 --- a/drivers/net/wireless/microchip/wilc1000/Kconfig +++ b/drivers/net/wireless/microchip/wilc1000/Kconfig @@ -27,6 +27,7 @@ config WILC1000_SPI depends on CFG80211 && INET && SPI select WILC1000 select CRC7 + select CRC_ITU_T help This module adds support for the SPI interface of adapters using WILC1000 chipset. The Atmel WILC1000 has a Serial Peripheral diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 0be93eabad69..1472e9843896 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -7,10 +7,27 @@ #include #include #include +#include #include "netdev.h" #include "cfg80211.h" +static bool enable_crc7; /* protect SPI commands with CRC7 */ +module_param(enable_crc7, bool, 0644); +MODULE_PARM_DESC(enable_crc7, + "Enable CRC7 checksum to protect command transfers\n" + "\t\t\tagainst corruption during the SPI transfer.\n" + "\t\t\tCommand transfers are short and the CPU-cycle cost\n" + "\t\t\tof enabling this is small."); + +static bool enable_crc16; /* protect SPI data with CRC16 */ +module_param(enable_crc16, bool, 0644); +MODULE_PARM_DESC(enable_crc16, + "Enable CRC16 checksum to protect data transfers\n" + "\t\t\tagainst corruption during the SPI transfer.\n" + "\t\t\tData transfers can be large and the CPU-cycle cost\n" + "\t\t\tof enabling this may be substantial."); + /* * For CMD_SINGLE_READ and CMD_INTERNAL_READ, WILC may insert one or * more zero bytes between the command response and the DATA Start tag @@ -22,7 +39,9 @@ #define WILC_SPI_RSP_HDR_EXTRA_DATA 8 struct wilc_spi { - int crc_off; + bool probing_crc; /* true if we're probing chip's CRC config */ + bool crc7_enabled; /* true if crc7 is currently enabled */ + bool crc16_enabled; /* true if crc16 is currently enabled */ }; static const struct wilc_hif_func wilc_hif_spi; @@ -314,7 +333,8 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) struct wilc_spi *spi_priv = wilc->bus_data; int ix, nbytes; int result = 0; - u8 cmd, order, crc[2] = {0}; + u8 cmd, order, crc[2]; + u16 crc_calc; /* * Data @@ -356,9 +376,12 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) } /* - * Write Crc + * Write CRC */ - if (!spi_priv->crc_off) { + if (spi_priv->crc16_enabled) { + crc_calc = crc_itu_t(0xffff, &b[ix], nbytes); + crc[0] = crc_calc >> 8; + crc[1] = crc_calc; if (wilc_spi_tx(wilc, crc, 2)) { dev_err(&spi->dev, "Failed data block crc write, bus error...\n"); result = -EINVAL; @@ -392,11 +415,11 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, struct spi_device *spi = to_spi_device(wilc->dev); struct wilc_spi *spi_priv = wilc->bus_data; u8 wb[32], rb[32]; - u8 crc[2]; int cmd_len, resp_len, i; + u16 crc_calc, crc_recv; struct wilc_spi_cmd *c; - struct wilc_spi_read_rsp_data *r_data; struct wilc_spi_rsp_data *r; + struct wilc_spi_read_rsp_data *r_data; memset(wb, 0x0, sizeof(wb)); memset(rb, 0x0, sizeof(rb)); @@ -420,7 +443,7 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, cmd_len = offsetof(struct wilc_spi_cmd, u.simple_cmd.crc); resp_len = sizeof(*r) + sizeof(*r_data) + WILC_SPI_RSP_HDR_EXTRA_DATA; - if (!spi_priv->crc_off) { + if (spi_priv->crc7_enabled) { c->u.simple_cmd.crc[0] = wilc_get_crc7(wb, cmd_len); cmd_len += 1; resp_len += 2; @@ -440,9 +463,10 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, r = (struct wilc_spi_rsp_data *)&rb[cmd_len]; if (r->rsp_cmd_type != cmd) { - dev_err(&spi->dev, - "Failed cmd response, cmd (%02x), resp (%02x)\n", - cmd, r->rsp_cmd_type); + if (!spi_priv->probing_crc) + dev_err(&spi->dev, + "Failed cmd, cmd (%02x), resp (%02x)\n", + cmd, r->rsp_cmd_type); return -EINVAL; } @@ -466,8 +490,16 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b, if (b) memcpy(b, r_data->data, 4); - if (!spi_priv->crc_off) - memcpy(crc, r_data->crc, 2); + if (!clockless && spi_priv->crc16_enabled) { + crc_recv = (r_data->crc[0] << 8) | r_data->crc[1]; + crc_calc = crc_itu_t(0xffff, r_data->data, 4); + if (crc_recv != crc_calc) { + dev_err(&spi->dev, "%s: bad CRC 0x%04x " + "(calculated 0x%04x)\n", __func__, + crc_recv, crc_calc); + return -EINVAL; + } + } return 0; } @@ -494,7 +526,7 @@ static int wilc_spi_write_cmd(struct wilc *wilc, u8 cmd, u32 adr, u32 data, c->u.internal_w_cmd.addr[1] = adr; c->u.internal_w_cmd.data = cpu_to_be32(data); cmd_len = offsetof(struct wilc_spi_cmd, u.internal_w_cmd.crc); - if (!spi_priv->crc_off) + if (spi_priv->crc7_enabled) c->u.internal_w_cmd.crc[0] = wilc_get_crc7(wb, cmd_len); } else if (cmd == CMD_SINGLE_WRITE) { c->u.w_cmd.addr[0] = adr >> 16; @@ -502,14 +534,14 @@ static int wilc_spi_write_cmd(struct wilc *wilc, u8 cmd, u32 adr, u32 data, c->u.w_cmd.addr[2] = adr; c->u.w_cmd.data = cpu_to_be32(data); cmd_len = offsetof(struct wilc_spi_cmd, u.w_cmd.crc); - if (!spi_priv->crc_off) + if (spi_priv->crc7_enabled) c->u.w_cmd.crc[0] = wilc_get_crc7(wb, cmd_len); } else { dev_err(&spi->dev, "write cmd [%x] not supported\n", cmd); return -EINVAL; } - if (!spi_priv->crc_off) + if (spi_priv->crc7_enabled) cmd_len += 1; resp_len = sizeof(*r); @@ -547,6 +579,7 @@ static int wilc_spi_dma_rw(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz) { struct spi_device *spi = to_spi_device(wilc->dev); struct wilc_spi *spi_priv = wilc->bus_data; + u16 crc_recv, crc_calc; u8 wb[32], rb[32]; int cmd_len, resp_len; int retry, ix = 0; @@ -565,7 +598,7 @@ static int wilc_spi_dma_rw(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz) c->u.dma_cmd.size[0] = sz >> 8; c->u.dma_cmd.size[1] = sz; cmd_len = offsetof(struct wilc_spi_cmd, u.dma_cmd.crc); - if (!spi_priv->crc_off) + if (spi_priv->crc7_enabled) c->u.dma_cmd.crc[0] = wilc_get_crc7(wb, cmd_len); } else if (cmd == CMD_DMA_EXT_WRITE || cmd == CMD_DMA_EXT_READ) { c->u.dma_cmd_ext.addr[0] = adr >> 16; @@ -575,14 +608,14 @@ static int wilc_spi_dma_rw(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz) c->u.dma_cmd_ext.size[1] = sz >> 8; c->u.dma_cmd_ext.size[2] = sz; cmd_len = offsetof(struct wilc_spi_cmd, u.dma_cmd_ext.crc); - if (!spi_priv->crc_off) + if (spi_priv->crc7_enabled) c->u.dma_cmd_ext.crc[0] = wilc_get_crc7(wb, cmd_len); } else { dev_err(&spi->dev, "dma read write cmd [%x] not supported\n", cmd); return -EINVAL; } - if (!spi_priv->crc_off) + if (spi_priv->crc7_enabled) cmd_len += 1; resp_len = sizeof(*r); @@ -648,12 +681,22 @@ static int wilc_spi_dma_rw(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz) } /* - * Read Crc + * Read CRC */ - if (!spi_priv->crc_off && wilc_spi_rx(wilc, crc, 2)) { - dev_err(&spi->dev, - "Failed block crc read, bus err\n"); - return -EINVAL; + if (spi_priv->crc16_enabled) { + if (wilc_spi_rx(wilc, crc, 2)) { + dev_err(&spi->dev, + "Failed block CRC read, bus err\n"); + return -EINVAL; + } + crc_recv = (crc[0] << 8) | crc[1]; + crc_calc = crc_itu_t(0xffff, &b[ix], nbytes); + if (crc_recv != crc_calc) { + dev_err(&spi->dev, "%s: bad CRC 0x%04x " + "(calculated 0x%04x)\n", __func__, + crc_recv, crc_calc); + return -EINVAL; + } } ix += nbytes; @@ -720,11 +763,13 @@ static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) { struct spi_device *spi = to_spi_device(wilc->dev); + struct wilc_spi *spi_priv = wilc->bus_data; int result; result = wilc_spi_single_read(wilc, CMD_INTERNAL_READ, adr, data, 0); if (result) { - dev_err(&spi->dev, "Failed internal read cmd...\n"); + if (!spi_priv->probing_crc) + dev_err(&spi->dev, "Failed internal read cmd...\n"); return result; } @@ -861,7 +906,7 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) u32 reg; u32 chipid; static int isinit; - int ret; + int ret, i; if (isinit) { ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid); @@ -876,50 +921,55 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) */ /* - * TODO: We can remove the CRC trials if there is a definite - * way to reset + * Infer the CRC settings that are currently in effect. This + * is necessary because we can't be sure that the chip has + * been RESET (e.g, after module unload and reload). */ - /* the SPI to it's initial value. */ - ret = spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®); - if (ret) { - /* - * Read failed. Try with CRC off. This might happen when module - * is removed but chip isn't reset - */ - spi_priv->crc_off = 1; - dev_err(&spi->dev, - "Failed read with CRC on, retrying with CRC off\n"); + spi_priv->probing_crc = true; + spi_priv->crc7_enabled = enable_crc7; + spi_priv->crc16_enabled = false; /* don't check CRC16 during probing */ + for (i = 0; i < 2; ++i) { ret = spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®); - if (ret) { - /* - * Read failed with both CRC on and off, - * something went bad - */ - dev_err(&spi->dev, "Failed internal read protocol\n"); - return ret; - } + if (ret == 0) + break; + spi_priv->crc7_enabled = !enable_crc7; } - if (spi_priv->crc_off == 0) { - /* disable crc checking: */ - reg &= ~(PROTOCOL_REG_CRC7_MASK | PROTOCOL_REG_CRC16_MASK); - - /* set the data packet size: */ - BUILD_BUG_ON(DATA_PKT_LOG_SZ < DATA_PKT_LOG_SZ_MIN - || DATA_PKT_LOG_SZ > DATA_PKT_LOG_SZ_MAX); - reg &= ~PROTOCOL_REG_PKT_SZ_MASK; - reg |= FIELD_PREP(PROTOCOL_REG_PKT_SZ_MASK, - DATA_PKT_LOG_SZ - DATA_PKT_LOG_SZ_MIN); - - ret = spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg); - if (ret) { - dev_err(&spi->dev, - "[wilc spi %d]: Failed internal write reg\n", - __LINE__); - return ret; - } - spi_priv->crc_off = 1; + if (ret) { + dev_err(&spi->dev, "Failed with CRC7 on and off.\n"); + return ret; } + /* set up the desired CRC configuration: */ + reg &= ~(PROTOCOL_REG_CRC7_MASK | PROTOCOL_REG_CRC16_MASK); + if (enable_crc7) + reg |= PROTOCOL_REG_CRC7_MASK; + if (enable_crc16) + reg |= PROTOCOL_REG_CRC16_MASK; + + /* set up the data packet size: */ + BUILD_BUG_ON(DATA_PKT_LOG_SZ < DATA_PKT_LOG_SZ_MIN + || DATA_PKT_LOG_SZ > DATA_PKT_LOG_SZ_MAX); + reg &= ~PROTOCOL_REG_PKT_SZ_MASK; + reg |= FIELD_PREP(PROTOCOL_REG_PKT_SZ_MASK, + DATA_PKT_LOG_SZ - DATA_PKT_LOG_SZ_MIN); + + /* establish the new setup: */ + ret = spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg); + if (ret) { + dev_err(&spi->dev, + "[wilc spi %d]: Failed internal write reg\n", + __LINE__); + return ret; + } + /* update our state to match new protocol settings: */ + spi_priv->crc7_enabled = enable_crc7; + spi_priv->crc16_enabled = enable_crc16; + + /* re-read to make sure new settings are in effect: */ + spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®); + + spi_priv->probing_crc = false; + /* * make sure can read back chip id correctly */ From a381b78a1598dde34a6e40dae2842024308a6ef2 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Wed, 3 Mar 2021 19:50:07 +0000 Subject: [PATCH 166/188] wilc1000: Bring MAC address setting in line with typical Linux behavior Linux network drivers normally disallow changing the MAC address when the interface is up. This driver has been different in that it allows to change the MAC address *only* when it's up. This patch brings wilc1000 behavior more in line with other network drivers. We could have replaced wilc_set_mac_addr() with eth_mac_addr() but that would break existing documentation on how to change the MAC address. Likewise, return -EADDRNOTAVAIL (not -EINVAL) when the specified MAC address is invalid or unavailable. Signed-off-by: David Mosberger-Tang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210303194846.1823596-1-davidm@egauge.net --- .../net/wireless/microchip/wilc1000/netdev.c | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index 9928e91c8ffa..7e4d9235251c 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -571,7 +571,6 @@ static int wilc_mac_open(struct net_device *ndev) { struct wilc_vif *vif = netdev_priv(ndev); struct wilc *wl = vif->wilc; - unsigned char mac_add[ETH_ALEN] = {0}; int ret = 0; struct mgmt_frame_regs mgmt_regs = {}; @@ -594,9 +593,12 @@ static int wilc_mac_open(struct net_device *ndev) wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, vif->idx); - wilc_get_mac_address(vif, mac_add); - netdev_dbg(ndev, "Mac address: %pM\n", mac_add); - ether_addr_copy(ndev->dev_addr, mac_add); + + if (is_valid_ether_addr(ndev->dev_addr)) + wilc_set_mac_address(vif, ndev->dev_addr); + else + wilc_get_mac_address(vif, ndev->dev_addr); + netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr); if (!is_valid_ether_addr(ndev->dev_addr)) { netdev_err(ndev, "Wrong MAC address\n"); @@ -635,7 +637,14 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) int srcu_idx; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; + + if (!vif->mac_opened) { + eth_commit_mac_addr_change(dev, p); + return 0; + } + + /* Verify MAC Address is not already in use: */ srcu_idx = srcu_read_lock(&wilc->srcu); list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) { @@ -643,7 +652,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) if (ether_addr_equal(addr->sa_data, mac_addr)) { if (vif != tmp_vif) { srcu_read_unlock(&wilc->srcu, srcu_idx); - return -EINVAL; + return -EADDRNOTAVAIL; } srcu_read_unlock(&wilc->srcu, srcu_idx); return 0; @@ -655,9 +664,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) if (result) return result; - ether_addr_copy(vif->bssid, addr->sa_data); - ether_addr_copy(vif->ndev->dev_addr, addr->sa_data); - + eth_commit_mac_addr_change(dev, p); return result; } From bf3365a856a19ac6b96973dbf17069e0e5013e28 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 5 Mar 2021 03:48:50 -0600 Subject: [PATCH 167/188] rtl8xxxu: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by replacing /* fall through */ comments with the new pseudo-keyword macro fallthrough; instead of letting the code fall through to the next case. Notice that Clang doesn't recognize /* fall through */ comments as implicit fall-through markings. Link: https://github.com/KSPP/linux/issues/115 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210305094850.GA141221@embeddedor --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 5cd7ef3625c5..afc97958fa4d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -1145,7 +1145,7 @@ void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) switch (hw->conf.chandef.width) { case NL80211_CHAN_WIDTH_20_NOHT: ht = false; - /* fall through */ + fallthrough; case NL80211_CHAN_WIDTH_20: opmode |= BW_OPMODE_20MHZ; rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); @@ -1272,7 +1272,7 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) switch (hw->conf.chandef.width) { case NL80211_CHAN_WIDTH_20_NOHT: ht = false; - /* fall through */ + fallthrough; case NL80211_CHAN_WIDTH_20: rf_mode_bw |= WMAC_TRXPTCL_CTL_BW_20; subchannel = 0; @@ -1741,11 +1741,11 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) case 3: priv->ep_tx_low_queue = 1; priv->ep_tx_count++; - /* fall through */ + fallthrough; case 2: priv->ep_tx_normal_queue = 1; priv->ep_tx_count++; - /* fall through */ + fallthrough; case 1: priv->ep_tx_high_queue = 1; priv->ep_tx_count++; From c81852a48e137c61e8c85863b5a5104acc1a8270 Mon Sep 17 00:00:00 2001 From: zuoqilin Date: Wed, 17 Mar 2021 14:33:53 +0800 Subject: [PATCH 168/188] mwifiex: Remove unneeded variable: "ret" Remove unneeded variable: "ret" Signed-off-by: zuoqilin Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210317063353.1055-1-zuoqilin1@163.com --- drivers/net/wireless/marvell/mwifiex/scan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index c2a685f63e95..0b877f3f6b97 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1211,7 +1211,6 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, struct mwifiex_bssdescriptor *bss_entry) { - int ret = 0; u8 element_id; struct ieee_types_fh_param_set *fh_param_set; struct ieee_types_ds_param_set *ds_param_set; @@ -1464,7 +1463,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, bytes_left -= total_ie_len; } /* while (bytes_left > 2) */ - return ret; + return 0; } /* From 2f51061edab942988b1a3c057d21228e938603db Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 19 Mar 2021 17:47:31 +0300 Subject: [PATCH 169/188] wilc1000: fix a loop timeout condition If the loop fails, the "while(trials--) {" loop will exit with "trials" set to -1. The test for that expects it to end with "trials" set to 0 so the warning message will not be printed. Fix this by changing from a post-op to a pre-op. This does mean that we only make 99 attempts instead of 100 but that's okay. Fixes: f135a1571a05 ("wilc1000: Support chip sleep over SPI") Signed-off-by: Dan Carpenter Acked-by: Ajay Singh Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/YFS5gx/gi70zlIaO@mwanda --- drivers/net/wireless/microchip/wilc1000/wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index d4a90c490084..2030fc7f53ca 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -575,7 +575,7 @@ void chip_allow_sleep(struct wilc *wilc) to_host_from_fw_bit = WILC_SPI_FW_TO_HOST_BIT; } - while (trials--) { + while (--trials) { ret = hif_func->hif_read_reg(wilc, to_host_from_fw_reg, ®); if (ret) return; From 431eb49e87ed8de7728b879e7288d85fb87f83ff Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 5 Apr 2021 11:09:14 +0200 Subject: [PATCH 170/188] rtl8xxxu: Simplify locking of a skb list accesses The 'c2hcmd_lock' spinlock is only used to protect some __skb_queue_tail() and __skb_dequeue() calls. Use the lock provided in the skb itself and call skb_queue_tail() and skb_dequeue(). These functions already include the correct locking. Signed-off-by: Christophe JAILLET Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/8bcec6429615aeb498482dc7e1955ce09b456585.1617613700.git.christophe.jaillet@wanadoo.fr --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 - drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 11 ++--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index d6d1be4169e5..d1a566cc0c9e 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1391,7 +1391,6 @@ struct rtl8xxxu_priv { struct delayed_work ra_watchdog; struct work_struct c2hcmd_work; struct sk_buff_head c2hcmd_queue; - spinlock_t c2hcmd_lock; struct rtl8xxxu_btcoex bt_coex; struct rtl8xxxu_ra_report ra_report; }; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index afc97958fa4d..9ff09cf7eb62 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -5423,7 +5423,6 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) struct rtl8xxxu_priv *priv; struct rtl8723bu_c2h *c2h; struct sk_buff *skb = NULL; - unsigned long flags; u8 bt_info = 0; struct rtl8xxxu_btcoex *btcoex; struct rtl8xxxu_ra_report *rarpt; @@ -5439,9 +5438,7 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) goto out; while (!skb_queue_empty(&priv->c2hcmd_queue)) { - spin_lock_irqsave(&priv->c2hcmd_lock, flags); - skb = __skb_dequeue(&priv->c2hcmd_queue); - spin_unlock_irqrestore(&priv->c2hcmd_lock, flags); + skb = skb_dequeue(&priv->c2hcmd_queue); c2h = (struct rtl8723bu_c2h *)skb->data; @@ -5499,7 +5496,6 @@ static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv, struct rtl8723bu_c2h *c2h = (struct rtl8723bu_c2h *)skb->data; struct device *dev = &priv->udev->dev; int len; - unsigned long flags; len = skb->len - 2; @@ -5538,9 +5534,7 @@ static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv, break; } - spin_lock_irqsave(&priv->c2hcmd_lock, flags); - __skb_queue_tail(&priv->c2hcmd_queue, skb); - spin_unlock_irqrestore(&priv->c2hcmd_lock, flags); + skb_queue_tail(&priv->c2hcmd_queue, skb); schedule_work(&priv->c2hcmd_work); } @@ -6606,7 +6600,6 @@ static int rtl8xxxu_probe(struct usb_interface *interface, spin_lock_init(&priv->rx_urb_lock); INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); - spin_lock_init(&priv->c2hcmd_lock); INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback); skb_queue_head_init(&priv->c2hcmd_queue); From 01414f8882f944fe106a52a6d4c2ae8869822195 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Mar 2021 11:43:34 +0100 Subject: [PATCH 171/188] libertas: avoid -Wempty-body warning Building without mesh supports shows a couple of warnings with 'make W=1': drivers/net/wireless/marvell/libertas/main.c: In function 'lbs_start_card': drivers/net/wireless/marvell/libertas/main.c:1068:37: error: suggest braces around empty body in an 'if' statement [-Werror=empty-body] 1068 | lbs_start_mesh(priv); Change the macros to use the usual "do { } while (0)" instead to shut up the warnings and make the code a litte more robust. Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210322104343.948660-4-arnd@kernel.org --- drivers/net/wireless/marvell/libertas/mesh.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/libertas/mesh.h b/drivers/net/wireless/marvell/libertas/mesh.h index d49717b20c09..44c4cd0230a8 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.h +++ b/drivers/net/wireless/marvell/libertas/mesh.h @@ -60,13 +60,13 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, #else -#define lbs_init_mesh(priv) -#define lbs_deinit_mesh(priv) -#define lbs_start_mesh(priv) -#define lbs_add_mesh(priv) -#define lbs_remove_mesh(priv) +#define lbs_init_mesh(priv) do { } while (0) +#define lbs_deinit_mesh(priv) do { } while (0) +#define lbs_start_mesh(priv) do { } while (0) +#define lbs_add_mesh(priv) do { } while (0) +#define lbs_remove_mesh(priv) do { } while (0) #define lbs_mesh_set_dev(priv, dev, rxpd) (dev) -#define lbs_mesh_set_txpd(priv, dev, txpd) +#define lbs_mesh_set_txpd(priv, dev, txpd) do { } while (0) #define lbs_mesh_set_channel(priv, channel) (0) #define lbs_mesh_activated(priv) (false) From 7b0e2c4f6be3ec68bf807c84e985e81c21404cd1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 13:57:14 +0100 Subject: [PATCH 172/188] wlcore: fix overlapping snprintf arguments in debugfs gcc complains about undefined behavior in calling snprintf() with the same buffer as input and output: drivers/net/wireless/ti/wl18xx/debugfs.c: In function 'diversity_num_of_packets_per_ant_read': drivers/net/wireless/ti/wl18xx/../wlcore/debugfs.h:86:3: error: 'snprintf' argument 4 overlaps destination object 'buf' [-Werror=restrict] 86 | snprintf(buf, sizeof(buf), "%s[%d] = %d\n", \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 87 | buf, i, stats->sub.name[i]); \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/net/wireless/ti/wl18xx/debugfs.c:24:2: note: in expansion of macro 'DEBUGFS_FWSTATS_FILE_ARRAY' 24 | DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c, wl18xx_acx_statistics) | ^~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/net/wireless/ti/wl18xx/debugfs.c:159:1: note: in expansion of macro 'WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY' 159 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(diversity, num_of_packets_per_ant, There are probably other ways of handling the debugfs file, without using on-stack buffers, but a simple workaround here is to remember the current position in the buffer and just keep printing in there. Fixes: bcca1bbdd412 ("wlcore: add debugfs macro to help print fw statistics arrays") Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210323125723.1961432-1-arnd@kernel.org --- drivers/net/wireless/ti/wlcore/boot.c | 13 ++++++++----- drivers/net/wireless/ti/wlcore/debugfs.h | 7 ++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index e14d88e558f0..85abd0a2d1c9 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c @@ -72,6 +72,7 @@ static int wlcore_validate_fw_ver(struct wl1271 *wl) unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_MULTI) ? wl->min_mr_fw_ver : wl->min_sr_fw_ver; char min_fw_str[32] = ""; + int off = 0; int i; /* the chip must be exactly equal */ @@ -105,13 +106,15 @@ static int wlcore_validate_fw_ver(struct wl1271 *wl) return 0; fail: - for (i = 0; i < NUM_FW_VER; i++) + for (i = 0; i < NUM_FW_VER && off < sizeof(min_fw_str); i++) if (min_ver[i] == WLCORE_FW_VER_IGNORE) - snprintf(min_fw_str, sizeof(min_fw_str), - "%s*.", min_fw_str); + off += snprintf(min_fw_str + off, + sizeof(min_fw_str) - off, + "*."); else - snprintf(min_fw_str, sizeof(min_fw_str), - "%s%u.", min_fw_str, min_ver[i]); + off += snprintf(min_fw_str + off, + sizeof(min_fw_str) - off, + "%u.", min_ver[i]); wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is invalid.\n" "Please use at least FW %s\n" diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index b143293e694f..715edfa5f89f 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h @@ -78,13 +78,14 @@ static ssize_t sub## _ ##name## _read(struct file *file, \ struct wl1271 *wl = file->private_data; \ struct struct_type *stats = wl->stats.fw_stats; \ char buf[DEBUGFS_FORMAT_BUFFER_SIZE] = ""; \ + int pos = 0; \ int i; \ \ wl1271_debugfs_update_stats(wl); \ \ - for (i = 0; i < len; i++) \ - snprintf(buf, sizeof(buf), "%s[%d] = %d\n", \ - buf, i, stats->sub.name[i]); \ + for (i = 0; i < len && pos < sizeof(buf); i++) \ + pos += snprintf(buf + pos, sizeof(buf), \ + "[%d] = %d\n", i, stats->sub.name[i]); \ \ return wl1271_format_buffer(userbuf, count, ppos, "%s", buf); \ } \ From 7909a590eba6d021f104958857cbc4f0089daceb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 14:16:28 +0100 Subject: [PATCH 173/188] airo: work around stack usage warning gcc-11 with KASAN on 32-bit arm produces a warning about a function that needs a lot of stack space: drivers/net/wireless/cisco/airo.c: In function 'setup_card.constprop': drivers/net/wireless/cisco/airo.c:3960:1: error: the frame size of 1512 bytes is larger than 1400 bytes [-Werror=frame-larger-than=] Most of this is from a single large structure that could be dynamically allocated or moved into the per-device structure. However, as the callers all seem to have a fairly well bounded call chain, the easiest change is to pull out the part of the function that needs the large variables into a separate function and mark that as noinline_for_stack. This does not reduce the total stack usage, but it gets rid of the warning and requires minimal changes otherwise. Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210323131634.2669455-1-arnd@kernel.org --- drivers/net/wireless/cisco/airo.c | 117 +++++++++++++++++------------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 60db38c38960..fd37d4d2983b 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -3817,6 +3817,68 @@ static inline void set_auth_type(struct airo_info *local, int auth_type) local->last_auth = auth_type; } +static int noinline_for_stack airo_readconfig(struct airo_info *ai, u8 *mac, int lock) +{ + int i, status; + /* large variables, so don't inline this function, + * maybe change to kmalloc + */ + tdsRssiRid rssi_rid; + CapabilityRid cap_rid; + + kfree(ai->SSID); + ai->SSID = NULL; + // general configuration (read/modify/write) + status = readConfigRid(ai, lock); + if (status != SUCCESS) return ERROR; + + status = readCapabilityRid(ai, &cap_rid, lock); + if (status != SUCCESS) return ERROR; + + status = PC4500_readrid(ai, RID_RSSI, &rssi_rid, sizeof(rssi_rid), lock); + if (status == SUCCESS) { + if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) + memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */ + } + else { + kfree(ai->rssi); + ai->rssi = NULL; + if (cap_rid.softCap & cpu_to_le16(8)) + ai->config.rmode |= RXMODE_NORMALIZED_RSSI; + else + airo_print_warn(ai->dev->name, "unknown received signal " + "level scale"); + } + ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; + set_auth_type(ai, AUTH_OPEN); + ai->config.modulation = MOD_CCK; + + if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && + (cap_rid.extSoftCap & cpu_to_le16(1)) && + micsetup(ai) == SUCCESS) { + ai->config.opmode |= MODE_MIC; + set_bit(FLAG_MIC_CAPABLE, &ai->flags); + } + + /* Save off the MAC */ + for (i = 0; i < ETH_ALEN; i++) { + mac[i] = ai->config.macAddr[i]; + } + + /* Check to see if there are any insmod configured + rates to add */ + if (rates[0]) { + memset(ai->config.rates, 0, sizeof(ai->config.rates)); + for (i = 0; i < 8 && rates[i]; i++) { + ai->config.rates[i] = rates[i]; + } + } + set_bit (FLAG_COMMIT, &ai->flags); + + return SUCCESS; +} + + static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) { Cmd cmd; @@ -3863,58 +3925,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (lock) up(&ai->sem); if (ai->config.len == 0) { - int i; - tdsRssiRid rssi_rid; - CapabilityRid cap_rid; - - kfree(ai->SSID); - ai->SSID = NULL; - // general configuration (read/modify/write) - status = readConfigRid(ai, lock); - if (status != SUCCESS) return ERROR; - - status = readCapabilityRid(ai, &cap_rid, lock); - if (status != SUCCESS) return ERROR; - - status = PC4500_readrid(ai, RID_RSSI,&rssi_rid, sizeof(rssi_rid), lock); - if (status == SUCCESS) { - if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) - memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */ - } - else { - kfree(ai->rssi); - ai->rssi = NULL; - if (cap_rid.softCap & cpu_to_le16(8)) - ai->config.rmode |= RXMODE_NORMALIZED_RSSI; - else - airo_print_warn(ai->dev->name, "unknown received signal " - "level scale"); - } - ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; - set_auth_type(ai, AUTH_OPEN); - ai->config.modulation = MOD_CCK; - - if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && - (cap_rid.extSoftCap & cpu_to_le16(1)) && - micsetup(ai) == SUCCESS) { - ai->config.opmode |= MODE_MIC; - set_bit(FLAG_MIC_CAPABLE, &ai->flags); - } - - /* Save off the MAC */ - for (i = 0; i < ETH_ALEN; i++) { - mac[i] = ai->config.macAddr[i]; - } - - /* Check to see if there are any insmod configured - rates to add */ - if (rates[0]) { - memset(ai->config.rates, 0, sizeof(ai->config.rates)); - for (i = 0; i < 8 && rates[i]; i++) { - ai->config.rates[i] = rates[i]; - } - } - set_bit (FLAG_COMMIT, &ai->flags); + status = airo_readconfig(ai, mac, lock); + if (status != SUCCESS) + return ERROR; } /* Setup the SSIDs if present */ From 3051946056c3b634605b275a223e48bcb796f49b Mon Sep 17 00:00:00 2001 From: Aditya Srivastava Date: Mon, 15 Mar 2021 23:02:59 +0530 Subject: [PATCH 174/188] rsi: fix comment syntax in file headers The opening comment mark '/**' is used for highlighting the beginning of kernel-doc comments. There are some files in drivers/net/wireless/rsi which follow this syntax in their file headers, i.e. start with '/**' like comments, which causes unexpected warnings from kernel-doc. E.g., running scripts/kernel-doc -none on drivers/net/wireless/rsi/rsi_coex.h causes this warning: "warning: wrong kernel-doc identifier on line: * Copyright (c) 2018 Redpine Signals Inc." Similarly for other files too. Provide a simple fix by replacing such occurrences with general comment format, i.e., "/*", to prevent kernel-doc from parsing it. Signed-off-by: Aditya Srivastava Reviewed-by: Randy Dunlap Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210315173259.8757-1-yashsri421@gmail.com --- drivers/net/wireless/rsi/rsi_boot_params.h | 2 +- drivers/net/wireless/rsi/rsi_coex.h | 2 +- drivers/net/wireless/rsi/rsi_common.h | 2 +- drivers/net/wireless/rsi/rsi_debugfs.h | 2 +- drivers/net/wireless/rsi/rsi_hal.h | 2 +- drivers/net/wireless/rsi/rsi_main.h | 2 +- drivers/net/wireless/rsi/rsi_mgmt.h | 2 +- drivers/net/wireless/rsi/rsi_ps.h | 2 +- drivers/net/wireless/rsi/rsi_sdio.h | 2 +- drivers/net/wireless/rsi/rsi_usb.h | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h index c1cf19d1e376..30e03aa6a529 100644 --- a/drivers/net/wireless/rsi/rsi_boot_params.h +++ b/drivers/net/wireless/rsi/rsi_boot_params.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2014 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_coex.h b/drivers/net/wireless/rsi/rsi_coex.h index 0fdc67f37a56..2c14e4c651b9 100644 --- a/drivers/net/wireless/rsi/rsi_coex.h +++ b/drivers/net/wireless/rsi/rsi_coex.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2018 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h index 60f1f286b030..7aa5124575cf 100644 --- a/drivers/net/wireless/rsi/rsi_common.h +++ b/drivers/net/wireless/rsi/rsi_common.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2014 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_debugfs.h b/drivers/net/wireless/rsi/rsi_debugfs.h index 580ad3b3f710..a6a28640ad40 100644 --- a/drivers/net/wireless/rsi/rsi_debugfs.h +++ b/drivers/net/wireless/rsi/rsi_debugfs.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2014 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h index 46e36df9e8e3..d044a440fa08 100644 --- a/drivers/net/wireless/rsi/rsi_hal.h +++ b/drivers/net/wireless/rsi/rsi_hal.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2017 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 73a19e43106b..a1065e5a92b4 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2014 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h index 2ce2dcf57441..236b21482f38 100644 --- a/drivers/net/wireless/rsi/rsi_mgmt.h +++ b/drivers/net/wireless/rsi/rsi_mgmt.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2014 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_ps.h b/drivers/net/wireless/rsi/rsi_ps.h index 98ff6a4ced57..0be2f1e201e5 100644 --- a/drivers/net/wireless/rsi/rsi_ps.h +++ b/drivers/net/wireless/rsi/rsi_ps.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2017 Redpine Signals Inc. * * Permission to use, copy, modify, and/or distribute this software for any diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h index 1c756263cf15..7c91b126b350 100644 --- a/drivers/net/wireless/rsi/rsi_sdio.h +++ b/drivers/net/wireless/rsi/rsi_sdio.h @@ -1,4 +1,4 @@ -/** +/* * @section LICENSE * Copyright (c) 2014 Redpine Signals Inc. * diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h index 8702f434b569..254d19b66412 100644 --- a/drivers/net/wireless/rsi/rsi_usb.h +++ b/drivers/net/wireless/rsi/rsi_usb.h @@ -1,4 +1,4 @@ -/** +/* * @section LICENSE * Copyright (c) 2014 Redpine Signals Inc. * From 705b5cfab183c78618c4757262ef741a8d2db7e9 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Tue, 23 Mar 2021 10:06:57 +0530 Subject: [PATCH 175/188] brcmfmac: A typo fix s/revsion/revision/ Signed-off-by: Bhaskar Chowdhury Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210323043657.1466296-1-unixbhaskar@gmail.com --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h index ee273e3bb101..e000ef78928c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h @@ -28,7 +28,7 @@ struct brcmf_usbdev { int ntxq, nrxq, rxsize; u32 bus_mtu; int devid; - int chiprev; /* chip revsion number */ + int chiprev; /* chip revision number */ }; /* IO Request Block (IRB) */ From d3240418a6623f0f308d013d621928f4ddf2b8d8 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Thu, 25 Mar 2021 14:41:51 +0800 Subject: [PATCH 176/188] libertas: struct lbs_private is declared duplicately struct lbs_private has been declared at 22nd line. Remove the duplicate. Signed-off-by: Wan Jiabing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210325064154.854245-1-wanjiabing@vivo.com --- drivers/net/wireless/marvell/libertas/decl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas/decl.h b/drivers/net/wireless/marvell/libertas/decl.h index 5d1e30e0c5db..c1e0388ef01d 100644 --- a/drivers/net/wireless/marvell/libertas/decl.h +++ b/drivers/net/wireless/marvell/libertas/decl.h @@ -23,7 +23,6 @@ struct lbs_private; typedef void (*lbs_fw_cb)(struct lbs_private *priv, int ret, const struct firmware *helper, const struct firmware *mainfw); -struct lbs_private; struct sk_buff; struct net_device; struct cmd_ds_command; From ec7480ed0801dbecd431ae5b7e5c1debcf173b63 Mon Sep 17 00:00:00 2001 From: Po-Hao Huang Date: Fri, 26 Mar 2021 17:21:47 +0800 Subject: [PATCH 177/188] rtw88: update statistics to fw for fine-tuning performance Since firmware can't have proper statistics, driver update the statistics periodically to firmware to assist in tuning performance. Signed-off-by: Po-Hao Huang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210326092147.30252-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw88/fw.c | 15 +++++++++++++++ drivers/net/wireless/realtek/rtw88/fw.h | 13 +++++++++++++ drivers/net/wireless/realtek/rtw88/phy.c | 1 + 3 files changed, 29 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 6649b84f6b1e..c46b34fbe8bf 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -500,6 +500,21 @@ void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect) rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } +void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev) +{ + struct rtw_traffic_stats *stats = &rtwdev->stats; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_PHY_INFO); + SET_WL_PHY_INFO_TX_TP(h2c_pkt, stats->tx_throughput); + SET_WL_PHY_INFO_RX_TP(h2c_pkt, stats->rx_throughput); + SET_WL_PHY_INFO_TX_RATE_DESC(h2c_pkt, dm_info->tx_rate); + SET_WL_PHY_INFO_RX_RATE_DESC(h2c_pkt, dm_info->curr_rx_rate); + SET_WL_PHY_INFO_RX_EVM(h2c_pkt, dm_info->rx_evm_dbm[RF_PATH_A]); + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev) { struct rtw_lps_conf *conf = &rtwdev->lps_conf; diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 39c905c1b1d8..5c89a54475dd 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -345,6 +345,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define H2C_CMD_LPS_PG_INFO 0x2b #define H2C_CMD_RA_INFO 0x40 #define H2C_CMD_RSSI_MONITOR 0x42 +#define H2C_CMD_WL_PHY_INFO 0x58 #define H2C_CMD_COEX_TDMA_TYPE 0x60 #define H2C_CMD_QUERY_BT_INFO 0x61 @@ -369,6 +370,17 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_WL_PHY_INFO_TX_TP(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(17, 8)) +#define SET_WL_PHY_INFO_RX_TP(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(27, 18)) +#define SET_WL_PHY_INFO_TX_RATE_DESC(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) +#define SET_WL_PHY_INFO_RX_RATE_DESC(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) +#define SET_WL_PHY_INFO_RX_EVM(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) + #define SET_PWR_MODE_SET_MODE(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8)) #define SET_PWR_MODE_SET_RLBM(h2c_pkt, value) \ @@ -559,6 +571,7 @@ void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data); void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn); +void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev); int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, u8 *buf, u32 size); void rtw_remove_rsvd_page(struct rtw_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index b3c0a38771a7..ae401a7bb91a 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -618,6 +618,7 @@ static void rtw_phy_pwr_track(struct rtw_dev *rtwdev) static void rtw_phy_ra_track(struct rtw_dev *rtwdev) { + rtw_fw_update_wl_phy_info(rtwdev); rtw_phy_ra_info_update(rtwdev); rtw_phy_rrsr_update(rtwdev); } From c434e5e48dc4e626364491455f97e2db0aa137b1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 28 Mar 2021 00:59:32 +0100 Subject: [PATCH 178/188] rsi: Use resume_noirq for SDIO The rsi_resume() does access the bus to enable interrupts on the RSI SDIO WiFi card, however when calling sdio_claim_host() in the resume path, it is possible the bus is already claimed and sdio_claim_host() spins indefinitelly. Enable the SDIO card interrupts in resume_noirq instead to prevent anything else from claiming the SDIO bus first. Fixes: 20db07332736 ("rsi: sdio suspend and resume support") Signed-off-by: Marek Vasut Cc: Amitkumar Karwar Cc: Angus Ainslie Cc: David S. Miller Cc: Jakub Kicinski Cc: Kalle Valo Cc: Karun Eagalapati Cc: Martin Kepplinger Cc: Sebastian Krzyszkowiak Cc: Siva Rebbagondla Cc: netdev@vger.kernel.org Cc: stable@vger.kernel.org Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210327235932.175896-1-marex@denx.de --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index fe0287b22a25..e0c502bc4270 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1513,7 +1513,7 @@ static int rsi_restore(struct device *dev) } static const struct dev_pm_ops rsi_pm_ops = { .suspend = rsi_suspend, - .resume = rsi_resume, + .resume_noirq = rsi_resume, .freeze = rsi_freeze, .thaw = rsi_thaw, .restore = rsi_restore, From 7f50ddc5d4fe2384fab1f185f0c548dd9da48328 Mon Sep 17 00:00:00 2001 From: Eric Lin Date: Wed, 31 Mar 2021 09:04:18 +0800 Subject: [PATCH 179/188] wl3501: fix typo of 'Networks' in comment Signed-off-by: Eric Lin Reported-by: Gustavo A. R. Silva Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210331010418.1632816-2-dslin1010@gmail.com --- drivers/net/wireless/wl3501.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index e98e04ee9a2c..5779ffbe5d0f 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -240,7 +240,7 @@ struct iw_mgmt_essid_pset { } __packed; /* - * According to 802.11 Wireless Netowors, the definitive guide - O'Reilly + * According to 802.11 Wireless Networks, the definitive guide - O'Reilly * Pg 75 */ #define IW_DATA_RATE_MAX_LABELS 8 From d663bc3317c9faf04c555331135a083b7648e939 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Wed, 31 Mar 2021 10:35:50 +0800 Subject: [PATCH 180/188] brcmfmac: Remove duplicate struct declaration struct brcmf_bus is declared twice. One has been declared at 37th line. Remove the duplicate. Signed-off-by: Wan Jiabing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210331023557.2804128-2-wanjiabing@vivo.com --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h index 4146faeed344..44ba6f389fa9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h @@ -112,7 +112,6 @@ do { \ extern int brcmf_msg_level; -struct brcmf_bus; struct brcmf_pub; #ifdef DEBUG struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); From 444a9af68b5cc2ca33d073605f747e0f00d6e7b9 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Wed, 31 Mar 2021 10:35:51 +0800 Subject: [PATCH 181/188] wilc1000: Remove duplicate struct declaration struct wilc is declared twice. One has been declared at 352nd line. Remove the duplicate. Signed-off-by: Wan Jiabing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210331023557.2804128-3-wanjiabing@vivo.com --- drivers/net/wireless/microchip/wilc1000/wlan.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index 6479acc12b95..771c25fa849b 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -398,7 +398,6 @@ struct wilc_cfg_rsp { u8 seq_no; }; -struct wilc; struct wilc_vif; int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, From 2ff25985ea9ccc6c9af2c77b0b49045adcc62e0e Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Thu, 1 Apr 2021 14:27:17 -0500 Subject: [PATCH 182/188] rtw88: Fix array overrun in rtw_get_tx_power_params() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a kernel with the Undefined Behaviour Sanity Checker (UBSAN) enabled, the following array overrun is logged: ================================================================================ UBSAN: array-index-out-of-bounds in /home/finger/wireless-drivers-next/drivers/net/wireless/realtek/rtw88/phy.c:1789:34 index 5 is out of range for type 'u8 [5]' CPU: 2 PID: 84 Comm: kworker/u16:3 Tainted: G O 5.12.0-rc5-00086-gd88bba47038e-dirty #651 Hardware name: TOSHIBA TECRA A50-A/TECRA A50-A, BIOS Version 4.50 09/29/2014 Workqueue: phy0 ieee80211_scan_work [mac80211] Call Trace: dump_stack+0x64/0x7c ubsan_epilogue+0x5/0x40 __ubsan_handle_out_of_bounds.cold+0x43/0x48 rtw_get_tx_power_params+0x83a/drivers/net/wireless/realtek/rtw88/0xad0 [rtw_core] ? rtw_pci_read16+0x20/0x20 [rtw_pci] ? check_hw_ready+0x50/0x90 [rtw_core] rtw_phy_get_tx_power_index+0x4d/0xd0 [rtw_core] rtw_phy_set_tx_power_level+0xee/0x1b0 [rtw_core] rtw_set_channel+0xab/0x110 [rtw_core] rtw_ops_config+0x87/0xc0 [rtw_core] ieee80211_hw_config+0x9d/0x130 [mac80211] ieee80211_scan_state_set_channel+0x81/0x170 [mac80211] ieee80211_scan_work+0x19f/0x2a0 [mac80211] process_one_work+0x1dd/0x3a0 worker_thread+0x49/0x330 ? rescuer_thread+0x3a0/0x3a0 kthread+0x134/0x150 ? kthread_create_worker_on_cpu+0x70/0x70 ret_from_fork+0x22/0x30 ================================================================================ The statement where an array is being overrun is shown in the following snippet: if (rate <= DESC_RATE11M) tx_power = pwr_idx_2g->cck_base[group]; else ====> tx_power = pwr_idx_2g->bw40_base[group]; The associated arrays are defined in main.h as follows: struct rtw_2g_txpwr_idx { u8 cck_base[6]; u8 bw40_base[5]; struct rtw_2g_1s_pwr_idx_diff ht_1s_diff; struct rtw_2g_ns_pwr_idx_diff ht_2s_diff; struct rtw_2g_ns_pwr_idx_diff ht_3s_diff; struct rtw_2g_ns_pwr_idx_diff ht_4s_diff; }; The problem arises because the value of group is 5 for channel 14. The trivial increase in the dimension of bw40_base fails as this struct must match the layout of efuse. The fix is to add the rate as an argument to rtw_get_channel_group() and set the group for channel 14 to 4 if rate <= DESC_RATE11M. This patch fixes commit fa6dfe6bff24 ("rtw88: resolve order of tx power setting routines") Fixes: fa6dfe6bff24 ("rtw88: resolve order of tx power setting routines") Reported-by: Богдан Пилипенко Signed-off-by: Larry Finger Signed-off-by: Ping-Ke Shih Cc: Stable Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210401192717.28927-1-Larry.Finger@lwfinger.net --- drivers/net/wireless/realtek/rtw88/phy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index ae401a7bb91a..fdd5da0bbfd8 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -1586,7 +1586,7 @@ void rtw_phy_load_tables(struct rtw_dev *rtwdev) } EXPORT_SYMBOL(rtw_phy_load_tables); -static u8 rtw_get_channel_group(u8 channel) +static u8 rtw_get_channel_group(u8 channel, u8 rate) { switch (channel) { default: @@ -1630,6 +1630,7 @@ static u8 rtw_get_channel_group(u8 channel) case 106: return 4; case 14: + return rate <= DESC_RATE11M ? 5 : 4; case 108: case 110: case 112: @@ -1881,7 +1882,7 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, s8 *remnant = &pwr_param->pwr_remnant; pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; - group = rtw_get_channel_group(ch); + group = rtw_get_channel_group(ch, rate); /* base power index for 2.4G/5G */ if (IS_CH_2G_BAND(ch)) { From a8e083ee8e2a6c94c29733835adae8bf5b832748 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Fri, 2 Apr 2021 11:26:27 -0700 Subject: [PATCH 183/188] mwl8k: Fix a double Free in mwl8k_probe_hw In mwl8k_probe_hw, hw->priv->txq is freed at the first time by dma_free_coherent() in the call chain: if(!priv->ap_fw)->mwl8k_init_txqs(hw)->mwl8k_txq_init(hw, i). Then in err_free_queues of mwl8k_probe_hw, hw->priv->txq is freed at the second time by mwl8k_txq_deinit(hw, i)->dma_free_coherent(). My patch set txq->txd to NULL after the first free to avoid the double free. Fixes: a66098daacee2 ("mwl8k: Marvell TOPDOG wireless driver") Signed-off-by: Lv Yunlong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210402182627.4256-1-lyl2019@mail.ustc.edu.cn --- drivers/net/wireless/marvell/mwl8k.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index c9f8c056aa51..84b32a5f01ee 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -1473,6 +1473,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) if (txq->skb == NULL) { dma_free_coherent(&priv->pdev->dev, size, txq->txd, txq->txd_dma); + txq->txd = NULL; return -ENOMEM; } From cf366b15470484f41a69fd634e4fc638bcce81ae Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 2 Apr 2021 23:31:00 +0200 Subject: [PATCH 184/188] carl9170: remove get_tid_h 'get_tid_h()' is the same as 'ieee80211_get_tid()'. So this function can be removed to save a few lines of code. Signed-off-by: Christophe JAILLET Acked-by: Christian Lamparter Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/68efad7a597159e22771d37fc8b4a8a613866d60.1617399010.git.christophe.jaillet@wanadoo.fr --- drivers/net/wireless/ath/carl9170/carl9170.h | 7 +------ drivers/net/wireless/ath/carl9170/tx.c | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 0d38100d6e4f..84a8ce0784b1 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -631,14 +631,9 @@ static inline u16 carl9170_get_seq(struct sk_buff *skb) return get_seq_h(carl9170_get_hdr(skb)); } -static inline u16 get_tid_h(struct ieee80211_hdr *hdr) -{ - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -} - static inline u16 carl9170_get_tid(struct sk_buff *skb) { - return get_tid_h(carl9170_get_hdr(skb)); + return ieee80211_get_tid(carl9170_get_hdr(skb)); } static inline struct ieee80211_vif * diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 6b8446ff48c8..88444fe6d1c6 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -394,7 +394,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, if (unlikely(!sta)) goto out_rcu; - tid = get_tid_h(hdr); + tid = ieee80211_get_tid(hdr); sta_info = (void *) sta->drv_priv; tid_info = rcu_dereference(sta_info->agg[tid]); From 5e6087559e85470fbf96b78c3deb79465cefcbfd Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 7 Apr 2021 17:46:06 +0800 Subject: [PATCH 185/188] wil6210: wmi: Remove useless code Fix the following whitescan warning: An unsigned value can never be less than 0. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1617788766-91433-1-git-send-email-jiapeng.chong@linux.alibaba.com --- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 823ec6e78a22..02ad44997e87 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1456,7 +1456,7 @@ static void wil_link_stats_store_basic(struct wil6210_vif *vif, u8 cid = basic->cid; struct wil_sta_info *sta; - if (cid < 0 || cid >= wil->max_assoc_sta) { + if (cid >= wil->max_assoc_sta) { wil_err(wil, "invalid cid %d\n", cid); return; } From fa84df705260513a6f690275d4fd2c0b054849b0 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 14 Apr 2021 14:39:14 +0800 Subject: [PATCH 186/188] bcma: remove unused function Fix the following clang warning: drivers/bcma/driver_mips.c:55:20: warning: unused function 'mips_write32' [-Wunused-function]. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1618382354-866-1-git-send-email-jiapeng.chong@linux.alibaba.com --- drivers/bcma/driver_mips.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index 87760aa60446..12aca34e8db0 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c @@ -52,13 +52,6 @@ static inline u32 mips_read32(struct bcma_drv_mips *mcore, return bcma_read32(mcore->core, offset); } -static inline void mips_write32(struct bcma_drv_mips *mcore, - u16 offset, - u32 value) -{ - bcma_write32(mcore->core, offset, value); -} - static u32 bcma_core_mips_irqflag(struct bcma_device *dev) { u32 flag; From c544d89b0d67d9b714846035913c270375c0ce00 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 Apr 2021 16:48:46 +0300 Subject: [PATCH 187/188] iwlwifi: pcie: don't enable BHs with IRQs disabled After the fix from Jiri that disabled local IRQs instead of just BHs (necessary to fix an issue with submitting a command with IRQs already disabled), there was still a situation in which we could deep in there enable BHs, if the device config sets the apmg_wake_up_wa configuration, which is true on all 7000 series devices. To fix that, but not require reverting commit 1ed08f6fb5ae ("iwlwifi: remove flags argument for nic_access"), split up nic access into a version with BH manipulation to use most of the time, and without it for this specific case where the local IRQs are already disabled. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210415164821.d0f2edda1651.I75f762e0bed38914d1300ea198b86dd449b4b206@changeid --- .../wireless/intel/iwlwifi/pcie/internal.h | 5 ++++ .../net/wireless/intel/iwlwifi/pcie/trans.c | 24 ++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index d9688c7bed07..76a512cd2e5c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -447,6 +447,11 @@ struct iwl_trans const struct iwl_cfg_trans_params *cfg_trans); void iwl_trans_pcie_free(struct iwl_trans *trans); +bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); +#define _iwl_trans_pcie_grab_nic_access(trans) \ + __cond_lock(nic_access_nobh, \ + likely(__iwl_trans_pcie_grab_nic_access(trans))) + /***************************************************** * RX ******************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 861dbc03d183..239bc177a3e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1978,12 +1978,16 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk) module_put(THIS_MODULE); } -static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) +/* + * This version doesn't disable BHs but rather assumes they're + * already disabled. + */ +bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) { int ret; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - spin_lock_bh(&trans_pcie->reg_lock); + spin_lock(&trans_pcie->reg_lock); if (trans_pcie->cmd_hold_nic_awake) goto out; @@ -2068,7 +2072,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) } err: - spin_unlock_bh(&trans_pcie->reg_lock); + spin_unlock(&trans_pcie->reg_lock); return false; } @@ -2081,6 +2085,20 @@ out: return true; } +static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) +{ + bool ret; + + local_bh_disable(); + ret = __iwl_trans_pcie_grab_nic_access(trans); + if (ret) { + /* keep BHs disabled until iwl_trans_pcie_release_nic_access */ + return ret; + } + local_bh_enable(); + return false; +} + static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 0346505351f5..4f6c187eed69 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -643,7 +643,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, * returned. This needs to be done only on NICs that have * apmg_wake_up_wa set (see above.) */ - if (!iwl_trans_grab_nic_access(trans)) + if (!_iwl_trans_pcie_grab_nic_access(trans)) return -EIO; /* @@ -652,7 +652,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, * already true, so it's OK to unconditionally set it to true. */ trans_pcie->cmd_hold_nic_awake = true; - spin_unlock_bh(&trans_pcie->reg_lock); + spin_unlock(&trans_pcie->reg_lock); return 0; } From fb8517f4fade44fa5e42e29ca4d6e4a7ed50b512 Mon Sep 17 00:00:00 2001 From: Po-Hao Huang Date: Fri, 16 Apr 2021 11:09:01 +0800 Subject: [PATCH 188/188] rtw88: 8822c: add CFO tracking Add CFO tracking, which stands for central frequency offset tracking, to adjust oscillator to align central frequency of connected AP. Then, it can yield better performance. Signed-off-by: Po-Hao Huang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210416030901.7099-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw88/coex.h | 8 ++ drivers/net/wireless/realtek/rtw88/debug.h | 1 + drivers/net/wireless/realtek/rtw88/main.h | 13 ++ drivers/net/wireless/realtek/rtw88/phy.c | 66 +++++++++ drivers/net/wireless/realtek/rtw88/phy.h | 2 + drivers/net/wireless/realtek/rtw88/reg.h | 1 + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 129 +++++++++++++++++- drivers/net/wireless/realtek/rtw88/rtw8822c.h | 5 + 8 files changed, 224 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h index 57018700ac39..fc61a0cab3e4 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.h +++ b/drivers/net/wireless/realtek/rtw88/coex.h @@ -406,4 +406,12 @@ void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type); void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type); void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m); +static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + return coex_stat->bt_disabled; +} + #endif diff --git a/drivers/net/wireless/realtek/rtw88/debug.h b/drivers/net/wireless/realtek/rtw88/debug.h index e16e0da26e77..c8efd1900a34 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.h +++ b/drivers/net/wireless/realtek/rtw88/debug.h @@ -19,6 +19,7 @@ enum rtw_debug_mask { RTW_DBG_PS = 0x00000400, RTW_DBG_BF = 0x00000800, RTW_DBG_WOW = 0x00001000, + RTW_DBG_CFO = 0x00002000, RTW_DBG_ALL = 0xffffffff }; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 98b18daae1fb..56a19b5a00fc 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -625,6 +625,7 @@ struct rtw_rx_pkt_stat { struct rtw_sta_info *si; struct ieee80211_vif *vif; + struct ieee80211_hdr *hdr; }; DECLARE_EWMA(tp, 10, 2); @@ -838,6 +839,8 @@ struct rtw_chip_ops { struct ieee80211_bss_conf *conf); void (*cfg_csi_rate)(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate, u8 fixrate_en, u8 *new_rate); + void (*cfo_init)(struct rtw_dev *rtwdev); + void (*cfo_track)(struct rtw_dev *rtwdev); /* for coex */ void (*coex_set_init)(struct rtw_dev *rtwdev); @@ -1499,6 +1502,15 @@ struct rtw_iqk_info { } result; }; +struct rtw_cfo_track { + bool is_adjust; + u8 crystal_cap; + s32 cfo_tail[RTW_RF_PATH_MAX]; + s32 cfo_cnt[RTW_RF_PATH_MAX]; + u32 packet_count; + u32 packet_count_pre; +}; + #define RRSR_INIT_2G 0x15f #define RRSR_INIT_5G 0x150 @@ -1552,6 +1564,7 @@ struct rtw_dm_info { u8 dack_dck[RTW_RF_PATH_MAX][2][DACK_DCK_BACKUP_NUM]; struct rtw_dpk_info dpk_info; + struct rtw_cfo_track cfo_track; /* [bandwidth 0:20M/1:40M][number of path] */ u8 cck_pd_lv[2][RTW_RF_PATH_MAX]; diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index fdd5da0bbfd8..8146acaf1893 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -119,6 +119,14 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) dm_info->cck_fa_avg = CCK_FA_AVG_RESET; } +static void rtw_phy_cfo_init(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + if (chip->ops->cfo_init) + chip->ops->cfo_init(rtwdev); +} + void rtw_phy_init(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; @@ -140,6 +148,7 @@ void rtw_phy_init(struct rtw_dev *rtwdev) rtw_phy_cck_pd_init(rtwdev); dm_info->iqk.done = false; + rtw_phy_cfo_init(rtwdev); } EXPORT_SYMBOL(rtw_phy_init); @@ -528,6 +537,62 @@ static void rtw_phy_dpk_track(struct rtw_dev *rtwdev) chip->ops->dpk_track(rtwdev); } +struct rtw_rx_addr_match_data { + struct rtw_dev *rtwdev; + struct ieee80211_hdr *hdr; + struct rtw_rx_pkt_stat *pkt_stat; + u8 *bssid; +}; + +static void rtw_phy_parsing_cfo_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_rx_addr_match_data *iter_data = data; + struct rtw_dev *rtwdev = iter_data->rtwdev; + struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + u8 *bssid = iter_data->bssid; + u8 i; + + if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) + return; + + for (i = 0; i < rtwdev->hal.rf_path_num; i++) { + cfo->cfo_tail[i] += pkt_stat->cfo_tail[i]; + cfo->cfo_cnt[i]++; + } + + cfo->packet_count++; +} + +void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat) +{ + struct ieee80211_hdr *hdr = pkt_stat->hdr; + struct rtw_rx_addr_match_data data = {}; + + if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status || + ieee80211_is_ctl(hdr->frame_control)) + return; + + data.rtwdev = rtwdev; + data.hdr = hdr; + data.pkt_stat = pkt_stat; + data.bssid = get_hdr_bssid(hdr); + + rtw_iterate_vifs_atomic(rtwdev, rtw_phy_parsing_cfo_iter, &data); +} +EXPORT_SYMBOL(rtw_phy_parsing_cfo); + +static void rtw_phy_cfo_track(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + if (chip->ops->cfo_track) + chip->ops->cfo_track(rtwdev); +} + #define CCK_PD_FA_LV1_MIN 1000 #define CCK_PD_FA_LV0_MAX 500 @@ -630,6 +695,7 @@ void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev) rtw_phy_dig(rtwdev); rtw_phy_cck_pd(rtwdev); rtw_phy_ra_track(rtwdev); + rtw_phy_cfo_track(rtwdev); rtw_phy_dpk_track(rtwdev); rtw_phy_pwr_track(rtwdev); } diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index a0742a69446d..0b6f2fc8193c 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -59,6 +59,8 @@ bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev); bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev); void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, struct rtw_swing_table *swing_table); +void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat); struct rtw_txpwr_lmt_cfg_pair { u8 regd; diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index a85fe29f13f7..95d29f522e27 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -516,6 +516,7 @@ #define BIT_RFE_BUF_EN BIT(3) #define REG_ANAPAR_XTAL_0 0x1040 +#define BIT_XCAP_0 GENMASK(23, 10) #define REG_CPU_DMEM_CON 0x1080 #define BIT_WL_PLATFORM_RST BIT(16) #define BIT_WL_SECURITY_CLK BIT(15) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 07ff0d442e5b..9f05c60c8a03 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -17,6 +17,7 @@ #include "util.h" #include "bf.h" #include "efuse.h" +#include "coex.h" #define IQK_DONE_8822C 0xaa @@ -39,7 +40,7 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) efuse->rfe_option = map->rfe_option; efuse->rf_board_option = map->rf_board_option; - efuse->crystal_cap = map->xtal_k; + efuse->crystal_cap = map->xtal_k & XCAP_MASK; efuse->channel_plan = map->channel_plan; efuse->country_code[0] = map->country_code[0]; efuse->country_code[1] = map->country_code[1]; @@ -1866,6 +1867,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, } dm_info->rx_evm_dbm[path] = evm_dbm; } + rtw_phy_parsing_cfo(rtwdev, pkt_stat); } static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, @@ -1921,6 +1923,7 @@ static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + pkt_stat->drv_info_sz); + pkt_stat->hdr = hdr; if (pkt_stat->phy_status) { phy_status = rx_desc + desc_sz + pkt_stat->shift; query_phy_status(rtwdev, phy_status, pkt_stat); @@ -3436,6 +3439,128 @@ static void rtw8822c_dpk_track(struct rtw_dev *rtwdev) } } +#define XCAP_EXTEND(val) ({typeof(val) _v = (val); _v | _v << 7; }) +static void rtw8822c_set_crystal_cap_reg(struct rtw_dev *rtwdev, u8 crystal_cap) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + u32 val = 0; + + val = XCAP_EXTEND(crystal_cap); + cfo->crystal_cap = crystal_cap; + rtw_write32_mask(rtwdev, REG_ANAPAR_XTAL_0, BIT_XCAP_0, val); +} + +static void rtw8822c_set_crystal_cap(struct rtw_dev *rtwdev, u8 crystal_cap) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + + if (cfo->crystal_cap == crystal_cap) + return; + + rtw8822c_set_crystal_cap_reg(rtwdev, crystal_cap); +} + +static void rtw8822c_cfo_tracking_reset(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + + cfo->is_adjust = true; + + if (cfo->crystal_cap > rtwdev->efuse.crystal_cap) + rtw8822c_set_crystal_cap(rtwdev, cfo->crystal_cap - 1); + else if (cfo->crystal_cap < rtwdev->efuse.crystal_cap) + rtw8822c_set_crystal_cap(rtwdev, cfo->crystal_cap + 1); +} + +static void rtw8822c_cfo_init(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + + cfo->crystal_cap = rtwdev->efuse.crystal_cap; + cfo->is_adjust = true; +} + +#define REPORT_TO_KHZ(val) ({typeof(val) _v = (val); (_v << 1) + (_v >> 1); }) +static s32 rtw8822c_cfo_calc_avg(struct rtw_dev *rtwdev, u8 path_num) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + s32 cfo_avg, cfo_path_sum = 0, cfo_rpt_sum; + u8 i; + + for (i = 0; i < path_num; i++) { + cfo_rpt_sum = REPORT_TO_KHZ(cfo->cfo_tail[i]); + + if (cfo->cfo_cnt[i]) + cfo_avg = cfo_rpt_sum / cfo->cfo_cnt[i]; + else + cfo_avg = 0; + + cfo_path_sum += cfo_avg; + } + + for (i = 0; i < path_num; i++) { + cfo->cfo_tail[i] = 0; + cfo->cfo_cnt[i] = 0; + } + + return cfo_path_sum / path_num; +} + +static void rtw8822c_cfo_need_adjust(struct rtw_dev *rtwdev, s32 cfo_avg) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + + if (!cfo->is_adjust) { + if (abs(cfo_avg) > CFO_TRK_ENABLE_TH) + cfo->is_adjust = true; + } else { + if (abs(cfo_avg) <= CFO_TRK_STOP_TH) + cfo->is_adjust = false; + } + + if (!rtw_coex_disabled(rtwdev)) { + cfo->is_adjust = false; + rtw8822c_set_crystal_cap(rtwdev, rtwdev->efuse.crystal_cap); + } +} + +static void rtw8822c_cfo_track(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_cfo_track *cfo = &dm_info->cfo_track; + u8 path_num = rtwdev->hal.rf_path_num; + s8 crystal_cap = cfo->crystal_cap; + s32 cfo_avg = 0; + + if (rtwdev->sta_cnt != 1) { + rtw8822c_cfo_tracking_reset(rtwdev); + return; + } + + if (cfo->packet_count == cfo->packet_count_pre) + return; + + cfo->packet_count_pre = cfo->packet_count; + cfo_avg = rtw8822c_cfo_calc_avg(rtwdev, path_num); + rtw8822c_cfo_need_adjust(rtwdev, cfo_avg); + + if (cfo->is_adjust) { + if (cfo_avg > CFO_TRK_ADJ_TH) + crystal_cap++; + else if (cfo_avg < -CFO_TRK_ADJ_TH) + crystal_cap--; + + crystal_cap = clamp_t(s8, crystal_cap, 0, XCAP_MASK); + rtw8822c_set_crystal_cap(rtwdev, (u8)crystal_cap); + } +} + static const struct rtw_phy_cck_pd_reg rtw8822c_cck_pd_reg[RTW_CHANNEL_WIDTH_40 + 1][RTW_RF_PATH_MAX] = { { @@ -4016,6 +4141,8 @@ static struct rtw_chip_ops rtw8822c_ops = { .config_bfee = rtw8822c_bf_config_bfee, .set_gid_table = rtw_bf_set_gid_table, .cfg_csi_rate = rtw_bf_cfg_csi_rate, + .cfo_init = rtw8822c_cfo_init, + .cfo_track = rtw8822c_cfo_track, .coex_set_init = rtw8822c_coex_cfg_init, .coex_set_ant_switch = NULL, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h index bb2495b8609e..e2b134ce0b3f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h @@ -165,6 +165,11 @@ const struct rtw_table name ## _tbl = { \ #define REG_ANAPARLDO_POW_MAC 0x0029 #define BIT_LDOE25_PON BIT(0) +#define XCAP_MASK GENMASK(6, 0) +#define CFO_TRK_ENABLE_TH 20 +#define CFO_TRK_STOP_TH 10 +#define CFO_TRK_ADJ_TH 10 + #define REG_TXDFIR0 0x808 #define REG_DFIRBW 0x810 #define REG_ANTMAP0 0x820