1 /* 2 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include "mt7601u.h" 16 #include "mac.h" 17 #include <linux/etherdevice.h> 18 19 static int mt7601u_start(struct ieee80211_hw *hw) 20 { 21 struct mt7601u_dev *dev = hw->priv; 22 int ret; 23 24 mutex_lock(&dev->mutex); 25 26 ret = mt7601u_mac_start(dev); 27 if (ret) 28 goto out; 29 30 ieee80211_queue_delayed_work(dev->hw, &dev->mac_work, 31 MT_CALIBRATE_INTERVAL); 32 ieee80211_queue_delayed_work(dev->hw, &dev->cal_work, 33 MT_CALIBRATE_INTERVAL); 34 out: 35 mutex_unlock(&dev->mutex); 36 return ret; 37 } 38 39 static void mt7601u_stop(struct ieee80211_hw *hw) 40 { 41 struct mt7601u_dev *dev = hw->priv; 42 43 mutex_lock(&dev->mutex); 44 45 cancel_delayed_work_sync(&dev->cal_work); 46 cancel_delayed_work_sync(&dev->mac_work); 47 mt7601u_mac_stop(dev); 48 49 mutex_unlock(&dev->mutex); 50 } 51 52 static int mt7601u_add_interface(struct ieee80211_hw *hw, 53 struct ieee80211_vif *vif) 54 { 55 struct mt7601u_dev *dev = hw->priv; 56 struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv; 57 unsigned int idx = 0; 58 unsigned int wcid = GROUP_WCID(idx); 59 60 /* Note: for AP do the AP-STA things mt76 does: 61 * - beacon offsets 62 * - do mac address tricks 63 * - shift vif idx 64 */ 65 mvif->idx = idx; 66 67 if (dev->wcid_mask[wcid / BITS_PER_LONG] & BIT(wcid % BITS_PER_LONG)) 68 return -ENOSPC; 69 dev->wcid_mask[wcid / BITS_PER_LONG] |= BIT(wcid % BITS_PER_LONG); 70 mvif->group_wcid.idx = wcid; 71 mvif->group_wcid.hw_key_idx = -1; 72 73 return 0; 74 } 75 76 static void mt7601u_remove_interface(struct ieee80211_hw *hw, 77 struct ieee80211_vif *vif) 78 { 79 struct mt7601u_dev *dev = hw->priv; 80 struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv; 81 unsigned int wcid = mvif->group_wcid.idx; 82 83 dev->wcid_mask[wcid / BITS_PER_LONG] &= ~BIT(wcid % BITS_PER_LONG); 84 } 85 86 static int mt7601u_config(struct ieee80211_hw *hw, u32 changed) 87 { 88 struct mt7601u_dev *dev = hw->priv; 89 int ret = 0; 90 91 mutex_lock(&dev->mutex); 92 93 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 94 ieee80211_stop_queues(hw); 95 ret = mt7601u_phy_set_channel(dev, &hw->conf.chandef); 96 ieee80211_wake_queues(hw); 97 } 98 99 mutex_unlock(&dev->mutex); 100 101 return ret; 102 } 103 104 static void 105 mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, 106 unsigned int *total_flags, u64 multicast) 107 { 108 struct mt7601u_dev *dev = hw->priv; 109 u32 flags = 0; 110 111 #define MT76_FILTER(_flag, _hw) do { \ 112 flags |= *total_flags & FIF_##_flag; \ 113 dev->rxfilter &= ~(_hw); \ 114 dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ 115 } while (0) 116 117 mutex_lock(&dev->mutex); 118 119 dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS; 120 121 MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC); 122 MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR); 123 MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR); 124 MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK | 125 MT_RX_FILTR_CFG_CTS | 126 MT_RX_FILTR_CFG_CFEND | 127 MT_RX_FILTR_CFG_CFACK | 128 MT_RX_FILTR_CFG_BA | 129 MT_RX_FILTR_CFG_CTRL_RSV); 130 MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL); 131 132 *total_flags = flags; 133 mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); 134 135 mutex_unlock(&dev->mutex); 136 } 137 138 static void 139 mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 140 struct ieee80211_bss_conf *info, u32 changed) 141 { 142 struct mt7601u_dev *dev = hw->priv; 143 144 mutex_lock(&dev->mutex); 145 146 if (changed & BSS_CHANGED_ASSOC) 147 mt7601u_phy_con_cal_onoff(dev, info); 148 149 if (changed & BSS_CHANGED_BSSID) { 150 mt7601u_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid); 151 152 /* Note: this is a hack because beacon_int is not changed 153 * on leave nor is any more appropriate event generated. 154 * rt2x00 doesn't seem to be bothered though. 155 */ 156 if (is_zero_ether_addr(info->bssid)) 157 mt7601u_mac_config_tsf(dev, false, 0); 158 } 159 160 if (changed & BSS_CHANGED_BASIC_RATES) { 161 mt7601u_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates); 162 mt7601u_wr(dev, MT_HT_FBK_CFG0, 0x65432100); 163 mt7601u_wr(dev, MT_HT_FBK_CFG1, 0xedcba980); 164 mt7601u_wr(dev, MT_LG_FBK_CFG0, 0xedcba988); 165 mt7601u_wr(dev, MT_LG_FBK_CFG1, 0x00002100); 166 } 167 168 if (changed & BSS_CHANGED_BEACON_INT) 169 mt7601u_mac_config_tsf(dev, true, info->beacon_int); 170 171 if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) 172 mt7601u_mac_set_protection(dev, info->use_cts_prot, 173 info->ht_operation_mode); 174 175 if (changed & BSS_CHANGED_ERP_PREAMBLE) 176 mt7601u_mac_set_short_preamble(dev, info->use_short_preamble); 177 178 if (changed & BSS_CHANGED_ERP_SLOT) { 179 int slottime = info->use_short_slot ? 9 : 20; 180 181 mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG, 182 MT_BKOFF_SLOT_CFG_SLOTTIME, slottime); 183 } 184 185 if (changed & BSS_CHANGED_ASSOC) 186 mt7601u_phy_recalibrate_after_assoc(dev); 187 188 mutex_unlock(&dev->mutex); 189 } 190 191 static int 192 mt76_wcid_alloc(struct mt7601u_dev *dev) 193 { 194 int i, idx = 0; 195 196 for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { 197 idx = ffs(~dev->wcid_mask[i]); 198 if (!idx) 199 continue; 200 201 idx--; 202 dev->wcid_mask[i] |= BIT(idx); 203 break; 204 } 205 206 idx = i * BITS_PER_LONG + idx; 207 if (idx > 119) 208 return -1; 209 210 return idx; 211 } 212 213 static int 214 mt7601u_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 215 struct ieee80211_sta *sta) 216 { 217 struct mt7601u_dev *dev = hw->priv; 218 struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; 219 struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv; 220 int ret = 0; 221 int idx = 0; 222 223 mutex_lock(&dev->mutex); 224 225 idx = mt76_wcid_alloc(dev); 226 if (idx < 0) { 227 ret = -ENOSPC; 228 goto out; 229 } 230 231 msta->wcid.idx = idx; 232 msta->wcid.hw_key_idx = -1; 233 mt7601u_mac_wcid_setup(dev, idx, mvif->idx, sta->addr); 234 mt76_clear(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx)); 235 rcu_assign_pointer(dev->wcid[idx], &msta->wcid); 236 mt7601u_mac_set_ampdu_factor(dev); 237 238 out: 239 mutex_unlock(&dev->mutex); 240 241 return ret; 242 } 243 244 static int 245 mt7601u_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 246 struct ieee80211_sta *sta) 247 { 248 struct mt7601u_dev *dev = hw->priv; 249 struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; 250 int idx = msta->wcid.idx; 251 252 mutex_lock(&dev->mutex); 253 rcu_assign_pointer(dev->wcid[idx], NULL); 254 mt76_set(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx)); 255 dev->wcid_mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG); 256 mt7601u_mac_wcid_setup(dev, idx, 0, NULL); 257 mt7601u_mac_set_ampdu_factor(dev); 258 mutex_unlock(&dev->mutex); 259 260 return 0; 261 } 262 263 static void 264 mt7601u_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 265 enum sta_notify_cmd cmd, struct ieee80211_sta *sta) 266 { 267 } 268 269 static void 270 mt7601u_sw_scan(struct ieee80211_hw *hw, 271 struct ieee80211_vif *vif, 272 const u8 *mac_addr) 273 { 274 struct mt7601u_dev *dev = hw->priv; 275 276 mt7601u_agc_save(dev); 277 set_bit(MT7601U_STATE_SCANNING, &dev->state); 278 } 279 280 static void 281 mt7601u_sw_scan_complete(struct ieee80211_hw *hw, 282 struct ieee80211_vif *vif) 283 { 284 struct mt7601u_dev *dev = hw->priv; 285 286 mt7601u_agc_restore(dev); 287 clear_bit(MT7601U_STATE_SCANNING, &dev->state); 288 } 289 290 static int 291 mt7601u_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 292 struct ieee80211_vif *vif, struct ieee80211_sta *sta, 293 struct ieee80211_key_conf *key) 294 { 295 struct mt7601u_dev *dev = hw->priv; 296 struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv; 297 struct mt76_sta *msta = sta ? (struct mt76_sta *) sta->drv_priv : NULL; 298 struct mt76_wcid *wcid = msta ? &msta->wcid : &mvif->group_wcid; 299 int idx = key->keyidx; 300 int ret; 301 302 if (cmd == SET_KEY) { 303 key->hw_key_idx = wcid->idx; 304 wcid->hw_key_idx = idx; 305 } else { 306 if (idx == wcid->hw_key_idx) 307 wcid->hw_key_idx = -1; 308 309 key = NULL; 310 } 311 312 if (!msta) { 313 if (key || wcid->hw_key_idx == idx) { 314 ret = mt76_mac_wcid_set_key(dev, wcid->idx, key); 315 if (ret) 316 return ret; 317 } 318 319 return mt76_mac_shared_key_setup(dev, mvif->idx, idx, key); 320 } 321 322 return mt76_mac_wcid_set_key(dev, msta->wcid.idx, key); 323 } 324 325 static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 326 { 327 struct mt7601u_dev *dev = hw->priv; 328 329 mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value); 330 331 return 0; 332 } 333 334 static int 335 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 336 struct ieee80211_ampdu_params *params) 337 { 338 struct mt7601u_dev *dev = hw->priv; 339 struct ieee80211_sta *sta = params->sta; 340 enum ieee80211_ampdu_mlme_action action = params->action; 341 u16 tid = params->tid; 342 u16 *ssn = ¶ms->ssn; 343 struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; 344 345 WARN_ON(msta->wcid.idx > GROUP_WCID(0)); 346 347 switch (action) { 348 case IEEE80211_AMPDU_RX_START: 349 mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid)); 350 break; 351 case IEEE80211_AMPDU_RX_STOP: 352 mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, 353 BIT(16 + tid)); 354 break; 355 case IEEE80211_AMPDU_TX_OPERATIONAL: 356 ieee80211_send_bar(vif, sta->addr, tid, msta->agg_ssn[tid]); 357 break; 358 case IEEE80211_AMPDU_TX_STOP_FLUSH: 359 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 360 break; 361 case IEEE80211_AMPDU_TX_START: 362 msta->agg_ssn[tid] = *ssn << 4; 363 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 364 break; 365 case IEEE80211_AMPDU_TX_STOP_CONT: 366 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 367 break; 368 } 369 370 return 0; 371 } 372 373 static void 374 mt76_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 375 struct ieee80211_sta *sta) 376 { 377 struct mt7601u_dev *dev = hw->priv; 378 struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; 379 struct ieee80211_sta_rates *rates; 380 struct ieee80211_tx_rate rate = {}; 381 382 rcu_read_lock(); 383 rates = rcu_dereference(sta->rates); 384 385 if (!rates) 386 goto out; 387 388 rate.idx = rates->rate[0].idx; 389 rate.flags = rates->rate[0].flags; 390 mt76_mac_wcid_set_rate(dev, &msta->wcid, &rate); 391 392 out: 393 rcu_read_unlock(); 394 } 395 396 const struct ieee80211_ops mt7601u_ops = { 397 .tx = mt7601u_tx, 398 .start = mt7601u_start, 399 .stop = mt7601u_stop, 400 .add_interface = mt7601u_add_interface, 401 .remove_interface = mt7601u_remove_interface, 402 .config = mt7601u_config, 403 .configure_filter = mt76_configure_filter, 404 .bss_info_changed = mt7601u_bss_info_changed, 405 .sta_add = mt7601u_sta_add, 406 .sta_remove = mt7601u_sta_remove, 407 .sta_notify = mt7601u_sta_notify, 408 .set_key = mt7601u_set_key, 409 .conf_tx = mt7601u_conf_tx, 410 .sw_scan_start = mt7601u_sw_scan, 411 .sw_scan_complete = mt7601u_sw_scan_complete, 412 .ampdu_action = mt76_ampdu_action, 413 .sta_rate_tbl_update = mt76_sta_rate_tbl_update, 414 .set_rts_threshold = mt7601u_set_rts_threshold, 415 }; 416