1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> 4 */ 5 #include "mt76.h" 6 7 static void mt76_scan_complete(struct mt76_dev *dev, bool abort) 8 { 9 struct mt76_phy *phy = dev->scan.phy; 10 struct cfg80211_scan_info info = { 11 .aborted = abort, 12 }; 13 14 if (!phy) 15 return; 16 17 clear_bit(MT76_SCANNING, &phy->state); 18 19 if (dev->scan.chan && phy->main_chandef.chan && 20 !test_bit(MT76_MCU_RESET, &dev->phy.state)) 21 mt76_set_channel(phy, &phy->main_chandef, false); 22 mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink); 23 memset(&dev->scan, 0, sizeof(dev->scan)); 24 if (!test_bit(MT76_MCU_RESET, &dev->phy.state)) 25 ieee80211_scan_completed(phy->hw, &info); 26 } 27 28 void mt76_abort_scan(struct mt76_dev *dev) 29 { 30 cancel_delayed_work_sync(&dev->scan_work); 31 mt76_scan_complete(dev, true); 32 } 33 EXPORT_SYMBOL_GPL(mt76_abort_scan); 34 35 static void 36 mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid) 37 { 38 struct cfg80211_scan_request *req = dev->scan.req; 39 struct ieee80211_vif *vif = dev->scan.vif; 40 struct mt76_vif_link *mvif = dev->scan.mlink; 41 enum nl80211_band band = dev->scan.chan->band; 42 struct mt76_phy *phy = dev->scan.phy; 43 struct ieee80211_tx_info *info; 44 struct sk_buff *skb; 45 46 skb = ieee80211_probereq_get(phy->hw, vif->addr, ssid->ssid, 47 ssid->ssid_len, req->ie_len); 48 if (!skb) 49 return; 50 51 if (is_unicast_ether_addr(req->bssid)) { 52 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 53 54 ether_addr_copy(hdr->addr1, req->bssid); 55 ether_addr_copy(hdr->addr3, req->bssid); 56 } 57 58 if (req->ie_len) 59 skb_put_data(skb, req->ie, req->ie_len); 60 61 skb->priority = 7; 62 skb_set_queue_mapping(skb, IEEE80211_AC_VO); 63 64 rcu_read_lock(); 65 66 if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) { 67 ieee80211_free_txskb(phy->hw, skb); 68 goto out; 69 } 70 71 info = IEEE80211_SKB_CB(skb); 72 if (req->no_cck) 73 info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE; 74 info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK; 75 76 mt76_tx(phy, NULL, mvif->wcid, skb); 77 78 out: 79 rcu_read_unlock(); 80 } 81 82 void mt76_scan_work(struct work_struct *work) 83 { 84 struct mt76_dev *dev = container_of(work, struct mt76_dev, 85 scan_work.work); 86 struct cfg80211_scan_request *req = dev->scan.req; 87 struct cfg80211_chan_def chandef = {}; 88 struct mt76_phy *phy = dev->scan.phy; 89 int duration = HZ / 9; /* ~110 ms */ 90 int i; 91 92 if (dev->scan.chan_idx >= req->n_channels) { 93 mt76_scan_complete(dev, false); 94 return; 95 } 96 97 if (dev->scan.chan && phy->num_sta) { 98 dev->scan.chan = NULL; 99 mt76_set_channel(phy, &phy->main_chandef, false); 100 goto out; 101 } 102 103 dev->scan.chan = req->channels[dev->scan.chan_idx++]; 104 cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20); 105 mt76_set_channel(phy, &chandef, true); 106 107 if (!req->n_ssids || 108 chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) 109 goto out; 110 111 duration = HZ / 16; /* ~60 ms */ 112 local_bh_disable(); 113 for (i = 0; i < req->n_ssids; i++) 114 mt76_scan_send_probe(dev, &req->ssids[i]); 115 local_bh_enable(); 116 117 out: 118 if (dev->scan.chan) 119 duration = max_t(int, duration, 120 msecs_to_jiffies(req->duration + 121 (req->duration >> 5))); 122 123 ieee80211_queue_delayed_work(dev->phy.hw, &dev->scan_work, duration); 124 } 125 126 int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 127 struct ieee80211_scan_request *req) 128 { 129 struct mt76_phy *phy = hw->priv; 130 struct mt76_dev *dev = phy->dev; 131 struct mt76_vif_link *mlink; 132 int ret = 0; 133 134 if (hw->wiphy->n_radio > 1) { 135 phy = dev->band_phys[req->req.channels[0]->band]; 136 if (!phy) 137 return -EINVAL; 138 } 139 140 mutex_lock(&dev->mutex); 141 142 if (dev->scan.req || phy->roc_vif || 143 test_bit(MT76_MCU_RESET, &dev->phy.state)) { 144 ret = -EBUSY; 145 goto out; 146 } 147 148 mlink = mt76_get_vif_phy_link(phy, vif); 149 if (IS_ERR(mlink)) { 150 ret = PTR_ERR(mlink); 151 goto out; 152 } 153 154 memset(&dev->scan, 0, sizeof(dev->scan)); 155 dev->scan.req = &req->req; 156 dev->scan.vif = vif; 157 dev->scan.phy = phy; 158 dev->scan.mlink = mlink; 159 ieee80211_queue_delayed_work(dev->phy.hw, &dev->scan_work, 0); 160 161 out: 162 mutex_unlock(&dev->mutex); 163 164 return ret; 165 } 166 EXPORT_SYMBOL_GPL(mt76_hw_scan); 167 168 void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 169 { 170 struct mt76_phy *phy = hw->priv; 171 172 mt76_abort_scan(phy->dev); 173 } 174 EXPORT_SYMBOL_GPL(mt76_cancel_hw_scan); 175