wifi: mt76: mt7921: add unified ROC cmd/event support
authorQuan Zhou <quan.zhou@mediatek.com>
Thu, 10 Nov 2022 21:23:45 +0000 (05:23 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 1 Dec 2022 16:29:13 +0000 (17:29 +0100)
Add unified ROC cmd/event which is only supported by the newer fw.

Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Co-developed-by: Kaikai Hu <kaikai.hu@mediatek.com>
Signed-off-by: Kaikai Hu <kaikai.hu@mediatek.com>
Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h

index cf34192a9d90b7512a20f4290c5dc5bb730c3f87..a4893331b7c3645ad45eac321d18125525de1926 100644 (file)
@@ -121,11 +121,13 @@ struct mt76_connac2_mcu_rxd {
 
        u8 eid;
        u8 seq;
-       u8 rsv[2];
-
+       u8 option;
+       u8 rsv;
        u8 ext_eid;
        u8 rsv1[2];
        u8 s2d_index;
+
+       u8 tlv[0];
 };
 
 struct mt76_connac2_patch_hdr {
@@ -957,6 +959,9 @@ enum {
        DEV_INFO_MAX_NUM
 };
 
+#define MCU_UNI_CMD_EVENT                       BIT(1)
+#define MCU_UNI_CMD_UNSOLICITED_EVENT           BIT(2)
+
 /* event table */
 enum {
        MCU_EVENT_TARGET_ADDRESS_LEN = 0x01,
@@ -1163,6 +1168,7 @@ enum {
        MCU_UNI_CMD_OFFLOAD = 0x06,
        MCU_UNI_CMD_HIF_CTRL = 0x07,
        MCU_UNI_CMD_SNIFFER = 0x24,
+       MCU_UNI_CMD_ROC = 0x27,
 };
 
 enum {
index 67bf92969a7b788df2e84bf500509edbd8cecba6..2b36c5f6eb40a8a6ab9f5abc7fe82b1da4b9357d 100644 (file)
@@ -302,6 +302,23 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
        dev_kfree_skb(skb);
 }
 
+static void
+mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
+                                   struct sk_buff *skb)
+{
+       struct mt76_connac2_mcu_rxd *rxd;
+
+       rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
+
+       switch (rxd->eid) {
+       case MCU_UNI_EVENT_ROC:
+               break;
+       default:
+               break;
+       }
+       dev_kfree_skb(skb);
+}
+
 void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
        struct mt76_connac2_mcu_rxd *rxd;
@@ -311,6 +328,11 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
 
        rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
 
+       if (rxd->option & MCU_UNI_CMD_UNSOLICITED_EVENT) {
+               mt7921_mcu_uni_rx_unsolicited_event(dev, skb);
+               return;
+       }
+
        if (rxd->eid == 0x6) {
                mt76_mcu_rx_event(&dev->mt76, skb);
                return;
@@ -636,6 +658,103 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
                                 &req_mu, sizeof(req_mu), false);
 }
 
+int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+                      struct ieee80211_channel *chan, int duration,
+                      enum mt7921_roc_req type, u8 token_id)
+{
+       int center_ch = ieee80211_frequency_to_channel(chan->center_freq);
+       struct mt7921_dev *dev = phy->dev;
+       struct {
+               struct {
+                       u8 rsv[4];
+               } __packed hdr;
+               struct roc_acquire_tlv {
+                       __le16 tag;
+                       __le16 len;
+                       u8 bss_idx;
+                       u8 tokenid;
+                       u8 control_channel;
+                       u8 sco;
+                       u8 band;
+                       u8 bw;
+                       u8 center_chan;
+                       u8 center_chan2;
+                       u8 bw_from_ap;
+                       u8 center_chan_from_ap;
+                       u8 center_chan2_from_ap;
+                       u8 reqtype;
+                       __le32 maxinterval;
+                       u8 dbdcband;
+                       u8 rsv[3];
+               } __packed roc;
+       } __packed req = {
+               .roc = {
+                       .tag = cpu_to_le16(UNI_ROC_ACQUIRE),
+                       .len = cpu_to_le16(sizeof(struct roc_acquire_tlv)),
+                       .tokenid = token_id,
+                       .reqtype = type,
+                       .maxinterval = cpu_to_le32(duration),
+                       .bss_idx = vif->mt76.idx,
+                       .control_channel = chan->hw_value,
+                       .bw = CMD_CBW_20MHZ,
+                       .bw_from_ap = CMD_CBW_20MHZ,
+                       .center_chan = center_ch,
+                       .center_chan_from_ap = center_ch,
+                       .dbdcband = 0xff, /* auto */
+               },
+       };
+
+       if (chan->hw_value < center_ch)
+               req.roc.sco = 1; /* SCA */
+       else if (chan->hw_value > center_ch)
+               req.roc.sco = 3; /* SCB */
+
+       switch (chan->band) {
+       case NL80211_BAND_6GHZ:
+               req.roc.band = 3;
+               break;
+       case NL80211_BAND_5GHZ:
+               req.roc.band = 2;
+               break;
+       default:
+               req.roc.band = 1;
+               break;
+       }
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
+                                &req, sizeof(req), false);
+}
+
+int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+                        u8 token_id)
+{
+       struct mt7921_dev *dev = phy->dev;
+       struct {
+               struct {
+                       u8 rsv[4];
+               } __packed hdr;
+               struct roc_abort_tlv {
+                       __le16 tag;
+                       __le16 len;
+                       u8 bss_idx;
+                       u8 tokenid;
+                       u8 dbdcband;
+                       u8 rsv[5];
+               } __packed abort;
+       } __packed req = {
+               .abort = {
+                       .tag = cpu_to_le16(UNI_ROC_ABORT),
+                       .len = cpu_to_le16(sizeof(struct roc_abort_tlv)),
+                       .tokenid = token_id,
+                       .bss_idx = vif->mt76.idx,
+                       .dbdcband = 0xff, /* auto*/
+               },
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
+                                &req, sizeof(req), false);
+}
+
 int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
 {
        struct mt7921_dev *dev = phy->dev;
index eaba114a9c7e40e266beeaa014856a80f79147ea..d9d78f6b088e13a1c596f1f4894d95f3083b9ef1 100644 (file)
 #define MT7921_SDIO_HDR_TX_BYTES       GENMASK(15, 0)
 #define MT7921_SDIO_HDR_PKT_TYPE       GENMASK(17, 16)
 
+#define MCU_UNI_EVENT_ROC  0x27
+
+enum {
+       UNI_ROC_ACQUIRE,
+       UNI_ROC_ABORT,
+       UNI_ROC_NUM
+};
+
+enum mt7921_roc_req {
+       MT7921_ROC_REQ_JOIN,
+       MT7921_ROC_REQ_ROC,
+       MT7921_ROC_REQ_NUM
+};
+
 enum mt7921_sdio_pkt_type {
        MT7921_SDIO_TXD,
        MT7921_SDIO_DATA,
@@ -508,4 +522,9 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
 
 int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
                       enum environment_cap env_cap);
+int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+                      struct ieee80211_channel *chan, int duration,
+                      enum mt7921_roc_req type, u8 token_id);
+int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+                        u8 token_id);
 #endif