summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
diff options
context:
space:
mode:
authorSean Wang <sean.wang@mediatek.com>2021-01-27 22:33:45 +0300
committerFelix Fietkau <nbd@nbd.name>2021-01-29 20:09:58 +0300
commit29f9d8b08b8cfaaceb4cb6199e38fbe6630d9706 (patch)
treed2f93f22986f2c1c7a4b696897374b58b18bb106 /drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
parent474a9f21e2e20ebe1cdaa093a77f0681273f4b03 (diff)
downloadlinux-29f9d8b08b8cfaaceb4cb6199e38fbe6630d9706.tar.xz
mt76: mt7921: introduce schedule scan support
introduce schedule scan to control mt7921 firmware to do background scan in defined plan to see if the matched SSID is available. Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Co-developed-by: Soul Huang <Soul.Huang@mediatek.com> Signed-off-by: Soul Huang <Soul.Huang@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7921/mcu.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index ee4b52558974..6f2b4086ca81 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -2361,6 +2361,89 @@ int mt7921_mcu_cancel_hw_scan(struct mt7921_phy *phy,
sizeof(req), false);
}
+int mt7921_mcu_sched_scan_req(struct mt7921_phy *phy,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *sreq)
+{
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct ieee80211_channel **scan_list = sreq->channels;
+ struct mt7921_dev *dev = phy->dev;
+ struct mt7921_mcu_scan_channel *chan;
+ struct mt7921_sched_scan_req *req;
+ struct cfg80211_match_set *match;
+ struct cfg80211_ssid *ssid;
+ struct sk_buff *skb;
+ int i;
+
+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
+ sizeof(*req) + sreq->ie_len);
+ if (!skb)
+ return -ENOMEM;
+
+ mvif->mt76.scan_seq_num = (mvif->mt76.scan_seq_num + 1) & 0x7f;
+
+ req = (struct mt7921_sched_scan_req *)skb_put(skb, sizeof(*req));
+ req->version = 1;
+ req->seq_num = mvif->mt76.scan_seq_num;
+
+ req->ssids_num = sreq->n_ssids;
+ for (i = 0; i < req->ssids_num; i++) {
+ ssid = &sreq->ssids[i];
+ memcpy(req->ssids[i].ssid, ssid->ssid, ssid->ssid_len);
+ req->ssids[i].ssid_len = cpu_to_le32(ssid->ssid_len);
+ }
+
+ req->match_num = sreq->n_match_sets;
+ for (i = 0; i < req->match_num; i++) {
+ match = &sreq->match_sets[i];
+ memcpy(req->match[i].ssid, match->ssid.ssid,
+ match->ssid.ssid_len);
+ req->match[i].rssi_th = cpu_to_le32(match->rssi_thold);
+ req->match[i].ssid_len = match->ssid.ssid_len;
+ }
+
+ req->channel_type = sreq->n_channels ? 4 : 0;
+ req->channels_num = min_t(u8, sreq->n_channels, 64);
+ for (i = 0; i < req->channels_num; i++) {
+ chan = &req->channels[i];
+ chan->band = scan_list[i]->band == NL80211_BAND_2GHZ ? 1 : 2;
+ chan->channel_num = scan_list[i]->hw_value;
+ }
+
+ req->intervals_num = sreq->n_scan_plans;
+ for (i = 0; i < req->intervals_num; i++)
+ req->intervals[i] = cpu_to_le16(sreq->scan_plans[i].interval);
+
+ if (sreq->ie_len > 0) {
+ req->ie_len = cpu_to_le16(sreq->ie_len);
+ memcpy(skb_put(skb, sreq->ie_len), sreq->ie, sreq->ie_len);
+ }
+
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_SCHED_SCAN_REQ,
+ false);
+}
+
+int mt7921_mcu_sched_scan_enable(struct mt7921_phy *phy,
+ struct ieee80211_vif *vif,
+ bool enable)
+{
+ struct mt7921_dev *dev = phy->dev;
+ struct {
+ u8 active; /* 0: enabled 1: disabled */
+ u8 rsv[3];
+ } __packed req = {
+ .active = !enable,
+ };
+
+ if (enable)
+ set_bit(MT76_HW_SCHED_SCANNING, &phy->mt76->state);
+ else
+ clear_bit(MT76_HW_SCHED_SCANNING, &phy->mt76->state);
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SCHED_SCAN_ENABLE, &req,
+ sizeof(req), false);
+}
+
u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u16 wlan_idx)
{
struct mt7921_mcu_wlan_info wtbl_info = {