developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 1 | From d3c4bfceae589098cb6cba5a3bb9125144df29fb Mon Sep 17 00:00:00 2001 |
| 2 | From: Michael-CY Lee <michael-cy.lee@mediatek.com> |
| 3 | Date: Tue, 14 May 2024 10:52:43 +0800 |
| 4 | Subject: [PATCH 131/199] mtk: mt76: mt7996: fix set beacon mcu command |
| 5 | |
| 6 | When stopping AP, mac80211 frees beacon template before it calls |
| 7 | driver's stop_ap operation. In other words, on the path of stopping |
| 8 | AP, ieee80211_beacon_get_template() must returns NULL in |
| 9 | mt7996_mcu_add_beacon(). In such case mt7996 immediately returns |
| 10 | -EINVAL without telling FW to disable the beacon. |
| 11 | |
| 12 | This commit refactors mt7996_mcu_add_beacon() so that FW can be |
| 13 | correctly informed when disabling AP interface. |
| 14 | |
| 15 | Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com> |
| 16 | --- |
| 17 | mt7996/mcu.c | 26 +++++++++++++++----------- |
| 18 | 1 file changed, 15 insertions(+), 11 deletions(-) |
| 19 | |
| 20 | diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
| 21 | index 2a2e6116..0a0df745 100644 |
| 22 | --- a/mt7996/mcu.c |
| 23 | +++ b/mt7996/mcu.c |
| 24 | @@ -3377,7 +3377,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, |
| 25 | struct sk_buff *skb, *rskb; |
| 26 | struct tlv *tlv; |
| 27 | struct bss_bcn_content_tlv *bcn; |
| 28 | - int len; |
| 29 | + int len, extra_len = 0; |
| 30 | |
| 31 | if (conf->nontransmitted) |
| 32 | return 0; |
| 33 | @@ -3388,28 +3388,32 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, |
| 34 | return PTR_ERR(rskb); |
| 35 | |
| 36 | skb = ieee80211_beacon_get_template(hw, conf->vif, &offs, conf->link_id); |
| 37 | - if (!skb) { |
| 38 | + if (en && !skb) { |
| 39 | dev_kfree_skb(rskb); |
| 40 | return -EINVAL; |
| 41 | } |
| 42 | |
| 43 | - if (skb->len > MT7996_MAX_BEACON_SIZE) { |
| 44 | - dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); |
| 45 | - dev_kfree_skb(rskb); |
| 46 | - dev_kfree_skb(skb); |
| 47 | - return -EINVAL; |
| 48 | - } |
| 49 | + if (skb) { |
| 50 | + if (skb->len > MT7996_MAX_BEACON_SIZE) { |
| 51 | + dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); |
| 52 | + dev_kfree_skb(rskb); |
| 53 | + dev_kfree_skb(skb); |
| 54 | + return -EINVAL; |
| 55 | + } |
| 56 | |
| 57 | - info = IEEE80211_SKB_CB(skb); |
| 58 | - info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx); |
| 59 | + extra_len = skb->len; |
| 60 | + } |
| 61 | |
| 62 | - len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + skb->len, 4); |
| 63 | + len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + extra_len, 4); |
| 64 | tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len); |
| 65 | bcn = (struct bss_bcn_content_tlv *)tlv; |
| 66 | bcn->enable = en; |
| 67 | if (!en) |
| 68 | goto out; |
| 69 | |
| 70 | + info = IEEE80211_SKB_CB(skb); |
| 71 | + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx); |
| 72 | + |
| 73 | mt7996_mcu_beacon_cont(dev, conf, rskb, skb, bcn, &offs); |
| 74 | mt7996_mcu_beacon_mbss(rskb, skb, conf, bcn, &offs); |
| 75 | mt7996_mcu_beacon_cntdwn(conf, rskb, skb, &offs); |
| 76 | -- |
| 77 | 2.18.0 |
| 78 | |