mt76: mt76_connac: move hw_scan and sched_scan routine in mt76_connac_mcu module

Move hw_scan/sched_scan in mt76_connac_mcu module in order to be reused in
mt7615 and mt7921 drivers

Signed-off-by: Lorenzo Bianconi <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Lorenzo Bianconi
2021-01-29 18:18:43 +01:00
committed by Felix Fietkau
parent 50349a8664
commit c88859180c
7 changed files with 359 additions and 356 deletions
+197
View File
@@ -982,5 +982,202 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
#define MT76_CONNAC_SCAN_CHANNEL_TIME 60
int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_scan_request *scan_req)
{
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 ext_channels_num = max_t(int, sreq->n_channels - 32, 0);
struct ieee80211_channel **scan_list = sreq->channels;
struct mt76_dev *mdev = phy->dev;
bool ext_phy = phy == mdev->phy2;
struct mt76_connac_mcu_scan_channel *chan;
struct mt76_connac_hw_scan_req *req;
struct sk_buff *skb;
skb = mt76_mcu_msg_alloc(mdev, NULL, sizeof(*req));
if (!skb)
return -ENOMEM;
set_bit(MT76_HW_SCANNING, &phy->state);
mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f;
req = (struct mt76_connac_hw_scan_req *)skb_put(skb, sizeof(*req));
req->seq_num = mvif->scan_seq_num | ext_phy << 7;
req->bss_idx = mvif->idx;
req->scan_type = sreq->n_ssids ? 1 : 0;
req->probe_req_num = sreq->n_ssids ? 2 : 0;
req->version = 1;
for (i = 0; i < sreq->n_ssids; i++) {
if (!sreq->ssids[i].ssid_len)
continue;
req->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
memcpy(req->ssids[i].ssid, sreq->ssids[i].ssid,
sreq->ssids[i].ssid_len);
n_ssids++;
}
req->ssid_type = n_ssids ? BIT(2) : BIT(0);
req->ssid_type_ext = n_ssids ? BIT(0) : 0;
req->ssids_num = n_ssids;
/* increase channel time for passive scan */
if (!sreq->n_ssids)
duration *= 2;
req->timeout_value = cpu_to_le16(sreq->n_channels * duration);
req->channel_min_dwell_time = cpu_to_le16(duration);
req->channel_dwell_time = cpu_to_le16(duration);
req->channels_num = min_t(u8, sreq->n_channels, 32);
req->ext_channels_num = min_t(u8, ext_channels_num, 32);
for (i = 0; i < req->channels_num + req->ext_channels_num; i++) {
if (i >= 32)
chan = &req->ext_channels[i - 32];
else
chan = &req->channels[i];
chan->band = scan_list[i]->band == NL80211_BAND_2GHZ ? 1 : 2;
chan->channel_num = scan_list[i]->hw_value;
}
req->channel_type = sreq->n_channels ? 4 : 0;
if (sreq->ie_len > 0) {
memcpy(req->ies, sreq->ie, sreq->ie_len);
req->ies_len = cpu_to_le16(sreq->ie_len);
}
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;
}
err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CMD_START_HW_SCAN, false);
if (err < 0)
clear_bit(MT76_HW_SCANNING, &phy->state);
return err;
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_hw_scan);
int mt76_connac_mcu_cancel_hw_scan(struct mt76_phy *phy,
struct ieee80211_vif *vif)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct {
u8 seq_num;
u8 is_ext_channel;
u8 rsv[2];
} __packed req = {
.seq_num = mvif->scan_seq_num,
};
if (test_and_clear_bit(MT76_HW_SCANNING, &phy->state)) {
struct cfg80211_scan_info info = {
.aborted = true,
};
ieee80211_scan_completed(phy->hw, &info);
}
return mt76_mcu_send_msg(phy->dev, MCU_CMD_CANCEL_HW_SCAN, &req,
sizeof(req), false);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_cancel_hw_scan);
int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *sreq)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct ieee80211_channel **scan_list = sreq->channels;
struct mt76_connac_mcu_scan_channel *chan;
struct mt76_connac_sched_scan_req *req;
struct mt76_dev *mdev = phy->dev;
bool ext_phy = phy == mdev->phy2;
struct cfg80211_match_set *match;
struct cfg80211_ssid *ssid;
struct sk_buff *skb;
int i;
skb = mt76_mcu_msg_alloc(mdev, NULL, sizeof(*req) + sreq->ie_len);
if (!skb)
return -ENOMEM;
mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f;
req = (struct mt76_connac_sched_scan_req *)skb_put(skb, sizeof(*req));
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,
sreq->mac_addr_mask);
req->scan_func = 1;
}
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(mdev, skb, MCU_CMD_SCHED_SCAN_REQ, false);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_sched_scan_req);
int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy,
struct ieee80211_vif *vif,
bool enable)
{
struct {
u8 active; /* 0: enabled 1: disabled */
u8 rsv[3];
} __packed req = {
.active = !enable,
};
if (enable)
set_bit(MT76_HW_SCHED_SCANNING, &phy->state);
else
clear_bit(MT76_HW_SCHED_SCANNING, &phy->state);
return mt76_mcu_send_msg(phy->dev, MCU_CMD_SCHED_SCAN_ENABLE, &req,
sizeof(req), false);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_sched_scan_enable);
MODULE_AUTHOR("Lorenzo Bianconi <[email protected]>");
MODULE_LICENSE("Dual BSD/GPL");