mt76: mt7615: introduce mt7615_mcu_set_channel_domain mcu command
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 2 Apr 2020 13:06:36 +0000 (15:06 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 12 May 2020 17:52:28 +0000 (19:52 +0200)
Introduce mt7615_mcu_set_channel_domain routines in order to instruct
the mcu about supported band/channels. This is a preliminary patch to
add hw scan support to mt7663e driver

Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h

index 6586176..20f6e31 100644 (file)
@@ -50,6 +50,7 @@ static int mt7615_start(struct ieee80211_hw *hw)
                mt7615_mac_enable_nf(dev, 1);
        }
 
+       mt7615_mcu_set_channel_domain(phy);
        mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
 
        set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
index 32e3e42..9ce08be 100644 (file)
@@ -135,14 +135,21 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,
        mcu_txd->pkt_type = MCU_PKT_ID;
        mcu_txd->seq = seq;
 
-       if (cmd & MCU_FW_PREFIX) {
+       switch (cmd & ~MCU_CMD_MASK) {
+       case MCU_FW_PREFIX:
                mcu_txd->set_query = MCU_Q_NA;
                mcu_txd->cid = mcu_cmd;
-       } else {
+               break;
+       case MCU_CE_PREFIX:
+               mcu_txd->set_query = MCU_Q_SET;
+               mcu_txd->cid = mcu_cmd;
+               break;
+       default:
                mcu_txd->cid = MCU_CMD_EXT_CID;
                mcu_txd->set_query = MCU_Q_SET;
                mcu_txd->ext_cid = cmd;
                mcu_txd->ext_cid_ack = 1;
+               break;
        }
 }
 
@@ -2421,3 +2428,64 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)
        return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req,
                                   sizeof(req), true);
 }
+
+int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy)
+{
+       struct mt76_phy *mphy = phy->mt76;
+       struct mt7615_dev *dev = phy->dev;
+       struct mt7615_mcu_channel_domain {
+               __le32 country_code; /* regulatory_request.alpha2 */
+               u8 bw_2g; /* BW_20_40M          0
+                          * BW_20M             1
+                          * BW_20_40_80M       2
+                          * BW_20_40_80_160M   3
+                          * BW_20_40_80_8080M  4
+                          */
+               u8 bw_5g;
+               __le16 pad;
+               u8 n_2ch;
+               u8 n_5ch;
+               __le16 pad2;
+       } __packed hdr = {
+               .bw_2g = 0,
+               .bw_5g = 3,
+               .n_2ch = mphy->sband_2g.sband.n_channels,
+               .n_5ch = mphy->sband_5g.sband.n_channels,
+       };
+       struct mt7615_mcu_chan {
+               __le16 hw_value;
+               __le16 pad;
+               __le32 flags;
+       } __packed;
+       int i, n_channels = hdr.n_2ch + hdr.n_5ch;
+       int len = sizeof(hdr) + n_channels * sizeof(struct mt7615_mcu_chan);
+       struct sk_buff *skb;
+
+       if (!mt7615_firmware_offload(dev))
+               return 0;
+
+       skb = mt7615_mcu_msg_alloc(NULL, len);
+       if (!skb)
+               return -ENOMEM;
+
+       skb_put_data(skb, &hdr, sizeof(hdr));
+
+       for (i = 0; i < n_channels; i++) {
+               struct ieee80211_channel *chan;
+               struct mt7615_mcu_chan channel;
+
+               if (i < hdr.n_2ch)
+                       chan = &mphy->sband_2g.sband.channels[i];
+               else
+                       chan = &mphy->sband_5g.sband.channels[i - hdr.n_2ch];
+
+               channel.hw_value = cpu_to_le16(chan->hw_value);
+               channel.flags = cpu_to_le32(chan->flags);
+               channel.pad = 0;
+
+               skb_put_data(skb, &channel, sizeof(channel));
+       }
+
+       return __mt76_mcu_skb_send_msg(&dev->mt76, skb,
+                                      MCU_CMD_SET_CHAN_DOMAIN, false);
+}
index d1f7391..c035413 100644 (file)
@@ -232,7 +232,9 @@ enum {
 
 #define MCU_FW_PREFIX          BIT(31)
 #define MCU_UNI_PREFIX         BIT(30)
-#define MCU_CMD_MASK           ~(MCU_FW_PREFIX | MCU_UNI_PREFIX)
+#define MCU_CE_PREFIX          BIT(29)
+#define MCU_CMD_MASK           ~(MCU_FW_PREFIX | MCU_UNI_PREFIX |      \
+                                 MCU_CE_PREFIX)
 
 enum {
        MCU_CMD_TARGET_ADDRESS_LEN_REQ = MCU_FW_PREFIX | 0x01,
@@ -275,6 +277,11 @@ enum {
        MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03,
 };
 
+/* offload mcu commands */
+enum {
+       MCU_CMD_SET_CHAN_DOMAIN = MCU_CE_PREFIX | 0x0f,
+};
+
 #define MCU_CMD_ACK            BIT(0)
 #define MCU_CMD_UNI            BIT(1)
 #define MCU_CMD_QUERY          BIT(2)
index e531c41..c61dc2f 100644 (file)
@@ -366,6 +366,11 @@ static inline void mt7615_irq_disable(struct mt7615_dev *dev, u32 mask)
        mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
 }
 
+static inline bool mt7615_firmware_offload(struct mt7615_dev *dev)
+{
+       return dev->fw_ver > MT7615_FIRMWARE_V2;
+}
+
 void mt7615_update_channel(struct mt76_dev *mdev);
 bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask);
 void mt7615_mac_reset_counters(struct mt7615_dev *dev);
@@ -395,6 +400,7 @@ int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index);
 void mt7615_mcu_exit(struct mt7615_dev *dev);
 void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,
                         int cmd, int *wait_seq);
+int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy);
 
 int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                          enum mt76_txq_id qid, struct mt76_wcid *wcid,