1 /* 2 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "mt76x2u.h" 18 19 static int mt76x2u_start(struct ieee80211_hw *hw) 20 { 21 struct mt76x02_dev *dev = hw->priv; 22 int ret; 23 24 mutex_lock(&dev->mt76.mutex); 25 26 ret = mt76x2u_mac_start(dev); 27 if (ret) 28 goto out; 29 30 set_bit(MT76_STATE_RUNNING, &dev->mt76.state); 31 32 out: 33 mutex_unlock(&dev->mt76.mutex); 34 return ret; 35 } 36 37 static void mt76x2u_stop(struct ieee80211_hw *hw) 38 { 39 struct mt76x02_dev *dev = hw->priv; 40 41 mutex_lock(&dev->mt76.mutex); 42 clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); 43 mt76x2u_stop_hw(dev); 44 mutex_unlock(&dev->mt76.mutex); 45 } 46 47 static int mt76x2u_add_interface(struct ieee80211_hw *hw, 48 struct ieee80211_vif *vif) 49 { 50 struct mt76x02_dev *dev = hw->priv; 51 52 if (!ether_addr_equal(dev->mt76.macaddr, vif->addr)) 53 mt76x02_mac_setaddr(dev, vif->addr); 54 55 mt76x02_vif_init(dev, vif, 0); 56 return 0; 57 } 58 59 static int 60 mt76x2u_set_channel(struct mt76x02_dev *dev, 61 struct cfg80211_chan_def *chandef) 62 { 63 int err; 64 65 cancel_delayed_work_sync(&dev->cal_work); 66 set_bit(MT76_RESET, &dev->mt76.state); 67 68 mt76_set_channel(&dev->mt76); 69 70 mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); 71 mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); 72 mt76x2_mac_stop(dev, false); 73 74 err = mt76x2u_phy_set_channel(dev, chandef); 75 76 mt76x2u_mac_resume(dev); 77 78 clear_bit(MT76_RESET, &dev->mt76.state); 79 mt76_txq_schedule_all(&dev->mt76); 80 81 return err; 82 } 83 84 static void 85 mt76x2u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 86 struct ieee80211_bss_conf *info, u32 changed) 87 { 88 struct mt76x02_dev *dev = hw->priv; 89 90 mutex_lock(&dev->mt76.mutex); 91 92 if (changed & BSS_CHANGED_ASSOC) { 93 mt76x2u_phy_channel_calibrate(dev); 94 mt76x2_apply_gain_adj(dev); 95 } 96 97 if (changed & BSS_CHANGED_BSSID) { 98 mt76_wr(dev, MT_MAC_BSSID_DW0, 99 get_unaligned_le32(info->bssid)); 100 mt76_wr(dev, MT_MAC_BSSID_DW1, 101 get_unaligned_le16(info->bssid + 4)); 102 } 103 104 mutex_unlock(&dev->mt76.mutex); 105 } 106 107 static int 108 mt76x2u_config(struct ieee80211_hw *hw, u32 changed) 109 { 110 struct mt76x02_dev *dev = hw->priv; 111 int err = 0; 112 113 mutex_lock(&dev->mt76.mutex); 114 115 if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 116 if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) 117 dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC; 118 else 119 dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC; 120 mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter); 121 } 122 123 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 124 ieee80211_stop_queues(hw); 125 err = mt76x2u_set_channel(dev, &hw->conf.chandef); 126 ieee80211_wake_queues(hw); 127 } 128 129 if (changed & IEEE80211_CONF_CHANGE_POWER) { 130 dev->mt76.txpower_conf = hw->conf.power_level * 2; 131 132 /* convert to per-chain power for 2x2 devices */ 133 dev->mt76.txpower_conf -= 6; 134 135 if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) 136 mt76x2_phy_set_txpower(dev); 137 } 138 139 mutex_unlock(&dev->mt76.mutex); 140 141 return err; 142 } 143 144 static void 145 mt76x2u_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 146 const u8 *mac) 147 { 148 struct mt76x02_dev *dev = hw->priv; 149 150 set_bit(MT76_SCANNING, &dev->mt76.state); 151 } 152 153 static void 154 mt76x2u_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 155 { 156 struct mt76x02_dev *dev = hw->priv; 157 158 clear_bit(MT76_SCANNING, &dev->mt76.state); 159 } 160 161 const struct ieee80211_ops mt76x2u_ops = { 162 .tx = mt76x02_tx, 163 .start = mt76x2u_start, 164 .stop = mt76x2u_stop, 165 .add_interface = mt76x2u_add_interface, 166 .remove_interface = mt76x02_remove_interface, 167 .sta_add = mt76x02_sta_add, 168 .sta_remove = mt76x02_sta_remove, 169 .set_key = mt76x02_set_key, 170 .ampdu_action = mt76x02_ampdu_action, 171 .config = mt76x2u_config, 172 .wake_tx_queue = mt76_wake_tx_queue, 173 .bss_info_changed = mt76x2u_bss_info_changed, 174 .configure_filter = mt76x02_configure_filter, 175 .conf_tx = mt76x02_conf_tx, 176 .sw_scan_start = mt76x2u_sw_scan, 177 .sw_scan_complete = mt76x2u_sw_scan_complete, 178 .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, 179 }; 180