Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
0004  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
0005  */
0006 
0007 #include "mt7601u.h"
0008 #include "mac.h"
0009 #include <linux/etherdevice.h>
0010 
0011 static int mt7601u_start(struct ieee80211_hw *hw)
0012 {
0013     struct mt7601u_dev *dev = hw->priv;
0014     int ret;
0015 
0016     mutex_lock(&dev->mutex);
0017 
0018     ret = mt7601u_mac_start(dev);
0019     if (ret)
0020         goto out;
0021 
0022     ieee80211_queue_delayed_work(dev->hw, &dev->mac_work,
0023                      MT_CALIBRATE_INTERVAL);
0024     ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
0025                      MT_CALIBRATE_INTERVAL);
0026 out:
0027     mutex_unlock(&dev->mutex);
0028     return ret;
0029 }
0030 
0031 static void mt7601u_stop(struct ieee80211_hw *hw)
0032 {
0033     struct mt7601u_dev *dev = hw->priv;
0034 
0035     mutex_lock(&dev->mutex);
0036 
0037     cancel_delayed_work_sync(&dev->cal_work);
0038     cancel_delayed_work_sync(&dev->mac_work);
0039     mt7601u_mac_stop(dev);
0040 
0041     mutex_unlock(&dev->mutex);
0042 }
0043 
0044 static int mt7601u_add_interface(struct ieee80211_hw *hw,
0045                  struct ieee80211_vif *vif)
0046 {
0047     struct mt7601u_dev *dev = hw->priv;
0048     struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
0049     unsigned int idx = 0;
0050     unsigned int wcid = GROUP_WCID(idx);
0051 
0052     /* Note: for AP do the AP-STA things mt76 does:
0053      *  - beacon offsets
0054      *  - do mac address tricks
0055      *  - shift vif idx
0056      */
0057     mvif->idx = idx;
0058 
0059     if (!ether_addr_equal(dev->macaddr, vif->addr))
0060         mt7601u_set_macaddr(dev, vif->addr);
0061 
0062     if (dev->wcid_mask[wcid / BITS_PER_LONG] & BIT(wcid % BITS_PER_LONG))
0063         return -ENOSPC;
0064     dev->wcid_mask[wcid / BITS_PER_LONG] |= BIT(wcid % BITS_PER_LONG);
0065     mvif->group_wcid.idx = wcid;
0066     mvif->group_wcid.hw_key_idx = -1;
0067 
0068     return 0;
0069 }
0070 
0071 static void mt7601u_remove_interface(struct ieee80211_hw *hw,
0072                      struct ieee80211_vif *vif)
0073 {
0074     struct mt7601u_dev *dev = hw->priv;
0075     struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
0076     unsigned int wcid = mvif->group_wcid.idx;
0077 
0078     dev->wcid_mask[wcid / BITS_PER_LONG] &= ~BIT(wcid % BITS_PER_LONG);
0079 }
0080 
0081 static int mt7601u_config(struct ieee80211_hw *hw, u32 changed)
0082 {
0083     struct mt7601u_dev *dev = hw->priv;
0084     int ret = 0;
0085 
0086     mutex_lock(&dev->mutex);
0087 
0088     if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
0089         ieee80211_stop_queues(hw);
0090         ret = mt7601u_phy_set_channel(dev, &hw->conf.chandef);
0091         ieee80211_wake_queues(hw);
0092     }
0093 
0094     mutex_unlock(&dev->mutex);
0095 
0096     return ret;
0097 }
0098 
0099 static void
0100 mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
0101               unsigned int *total_flags, u64 multicast)
0102 {
0103     struct mt7601u_dev *dev = hw->priv;
0104     u32 flags = 0;
0105 
0106 #define MT76_FILTER(_flag, _hw) do { \
0107         flags |= *total_flags & FIF_##_flag;            \
0108         dev->rxfilter &= ~(_hw);                \
0109         dev->rxfilter |= !(flags & FIF_##_flag) * (_hw);    \
0110     } while (0)
0111 
0112     mutex_lock(&dev->mutex);
0113 
0114     dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
0115 
0116     MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC);
0117     MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
0118     MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
0119     MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
0120                  MT_RX_FILTR_CFG_CTS |
0121                  MT_RX_FILTR_CFG_CFEND |
0122                  MT_RX_FILTR_CFG_CFACK |
0123                  MT_RX_FILTR_CFG_BA |
0124                  MT_RX_FILTR_CFG_CTRL_RSV);
0125     MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL);
0126 
0127     *total_flags = flags;
0128     mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
0129 
0130     mutex_unlock(&dev->mutex);
0131 }
0132 
0133 static void
0134 mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0135              struct ieee80211_bss_conf *info, u64 changed)
0136 {
0137     struct mt7601u_dev *dev = hw->priv;
0138 
0139     mutex_lock(&dev->mutex);
0140 
0141     if (changed & BSS_CHANGED_ASSOC)
0142         mt7601u_phy_con_cal_onoff(dev, info);
0143 
0144     if (changed & BSS_CHANGED_BSSID) {
0145         mt7601u_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid);
0146 
0147         /* Note: this is a hack because beacon_int is not changed
0148          *   on leave nor is any more appropriate event generated.
0149          *   rt2x00 doesn't seem to be bothered though.
0150          */
0151         if (is_zero_ether_addr(info->bssid))
0152             mt7601u_mac_config_tsf(dev, false, 0);
0153     }
0154 
0155     if (changed & BSS_CHANGED_BASIC_RATES) {
0156         mt7601u_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);
0157         mt7601u_wr(dev, MT_HT_FBK_CFG0, 0x65432100);
0158         mt7601u_wr(dev, MT_HT_FBK_CFG1, 0xedcba980);
0159         mt7601u_wr(dev, MT_LG_FBK_CFG0, 0xedcba988);
0160         mt7601u_wr(dev, MT_LG_FBK_CFG1, 0x00002100);
0161     }
0162 
0163     if (changed & BSS_CHANGED_BEACON_INT)
0164         mt7601u_mac_config_tsf(dev, true, info->beacon_int);
0165 
0166     if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
0167         mt7601u_mac_set_protection(dev, info->use_cts_prot,
0168                        info->ht_operation_mode);
0169 
0170     if (changed & BSS_CHANGED_ERP_PREAMBLE)
0171         mt7601u_mac_set_short_preamble(dev, info->use_short_preamble);
0172 
0173     if (changed & BSS_CHANGED_ERP_SLOT) {
0174         int slottime = info->use_short_slot ? 9 : 20;
0175 
0176         mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG,
0177                    MT_BKOFF_SLOT_CFG_SLOTTIME, slottime);
0178     }
0179 
0180     if (changed & BSS_CHANGED_ASSOC)
0181         mt7601u_phy_recalibrate_after_assoc(dev);
0182 
0183     mutex_unlock(&dev->mutex);
0184 }
0185 
0186 static int
0187 mt76_wcid_alloc(struct mt7601u_dev *dev)
0188 {
0189     int i, idx = 0;
0190 
0191     for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
0192         idx = ffs(~dev->wcid_mask[i]);
0193         if (!idx)
0194             continue;
0195 
0196         idx--;
0197         dev->wcid_mask[i] |= BIT(idx);
0198         break;
0199     }
0200 
0201     idx = i * BITS_PER_LONG + idx;
0202     if (idx > 119)
0203         return -1;
0204 
0205     return idx;
0206 }
0207 
0208 static int
0209 mt7601u_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0210         struct ieee80211_sta *sta)
0211 {
0212     struct mt7601u_dev *dev = hw->priv;
0213     struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
0214     struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
0215     int ret = 0;
0216     int idx = 0;
0217 
0218     mutex_lock(&dev->mutex);
0219 
0220     idx = mt76_wcid_alloc(dev);
0221     if (idx < 0) {
0222         ret = -ENOSPC;
0223         goto out;
0224     }
0225 
0226     msta->wcid.idx = idx;
0227     msta->wcid.hw_key_idx = -1;
0228     mt7601u_mac_wcid_setup(dev, idx, mvif->idx, sta->addr);
0229     mt76_clear(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
0230     rcu_assign_pointer(dev->wcid[idx], &msta->wcid);
0231     mt7601u_mac_set_ampdu_factor(dev);
0232 
0233 out:
0234     mutex_unlock(&dev->mutex);
0235 
0236     return ret;
0237 }
0238 
0239 static int
0240 mt7601u_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0241            struct ieee80211_sta *sta)
0242 {
0243     struct mt7601u_dev *dev = hw->priv;
0244     struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
0245     int idx = msta->wcid.idx;
0246 
0247     mutex_lock(&dev->mutex);
0248     rcu_assign_pointer(dev->wcid[idx], NULL);
0249     mt76_set(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
0250     dev->wcid_mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG);
0251     mt7601u_mac_wcid_setup(dev, idx, 0, NULL);
0252     mt7601u_mac_set_ampdu_factor(dev);
0253     mutex_unlock(&dev->mutex);
0254 
0255     return 0;
0256 }
0257 
0258 static void
0259 mt7601u_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0260            enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
0261 {
0262 }
0263 
0264 static void
0265 mt7601u_sw_scan(struct ieee80211_hw *hw,
0266         struct ieee80211_vif *vif,
0267         const u8 *mac_addr)
0268 {
0269     struct mt7601u_dev *dev = hw->priv;
0270 
0271     mt7601u_agc_save(dev);
0272     set_bit(MT7601U_STATE_SCANNING, &dev->state);
0273 }
0274 
0275 static void
0276 mt7601u_sw_scan_complete(struct ieee80211_hw *hw,
0277              struct ieee80211_vif *vif)
0278 {
0279     struct mt7601u_dev *dev = hw->priv;
0280 
0281     mt7601u_agc_restore(dev);
0282     clear_bit(MT7601U_STATE_SCANNING, &dev->state);
0283 
0284     ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
0285                      MT_CALIBRATE_INTERVAL);
0286     if (dev->freq_cal.enabled)
0287         ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work,
0288                          MT_FREQ_CAL_INIT_DELAY);
0289 }
0290 
0291 static int
0292 mt7601u_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
0293         struct ieee80211_vif *vif, struct ieee80211_sta *sta,
0294         struct ieee80211_key_conf *key)
0295 {
0296     struct mt7601u_dev *dev = hw->priv;
0297     struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
0298     struct mt76_sta *msta = sta ? (struct mt76_sta *) sta->drv_priv : NULL;
0299     struct mt76_wcid *wcid = msta ? &msta->wcid : &mvif->group_wcid;
0300     int idx = key->keyidx;
0301     int ret;
0302 
0303     /* fall back to sw encryption for unsupported ciphers */
0304     switch (key->cipher) {
0305     case WLAN_CIPHER_SUITE_WEP40:
0306     case WLAN_CIPHER_SUITE_WEP104:
0307     case WLAN_CIPHER_SUITE_TKIP:
0308     case WLAN_CIPHER_SUITE_CCMP:
0309         break;
0310     default:
0311         return -EOPNOTSUPP;
0312     }
0313 
0314     if (cmd == SET_KEY) {
0315         key->hw_key_idx = wcid->idx;
0316         wcid->hw_key_idx = idx;
0317     } else {
0318         if (idx == wcid->hw_key_idx)
0319             wcid->hw_key_idx = -1;
0320 
0321         key = NULL;
0322     }
0323 
0324     if (!msta) {
0325         if (key || wcid->hw_key_idx == idx) {
0326             ret = mt76_mac_wcid_set_key(dev, wcid->idx, key);
0327             if (ret)
0328                 return ret;
0329         }
0330 
0331         return mt76_mac_shared_key_setup(dev, mvif->idx, idx, key);
0332     }
0333 
0334     return mt76_mac_wcid_set_key(dev, msta->wcid.idx, key);
0335 }
0336 
0337 static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
0338 {
0339     struct mt7601u_dev *dev = hw->priv;
0340 
0341     mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value);
0342 
0343     return 0;
0344 }
0345 
0346 static int
0347 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0348           struct ieee80211_ampdu_params *params)
0349 {
0350     struct mt7601u_dev *dev = hw->priv;
0351     struct ieee80211_sta *sta = params->sta;
0352     enum ieee80211_ampdu_mlme_action action = params->action;
0353     u16 tid = params->tid;
0354     u16 ssn = params->ssn;
0355     struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
0356 
0357     WARN_ON(msta->wcid.idx > GROUP_WCID(0));
0358 
0359     switch (action) {
0360     case IEEE80211_AMPDU_RX_START:
0361         mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
0362         break;
0363     case IEEE80211_AMPDU_RX_STOP:
0364         mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4,
0365                BIT(16 + tid));
0366         break;
0367     case IEEE80211_AMPDU_TX_OPERATIONAL:
0368         ieee80211_send_bar(vif, sta->addr, tid, msta->agg_ssn[tid]);
0369         break;
0370     case IEEE80211_AMPDU_TX_STOP_FLUSH:
0371     case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
0372         break;
0373     case IEEE80211_AMPDU_TX_START:
0374         msta->agg_ssn[tid] = ssn << 4;
0375         return IEEE80211_AMPDU_TX_START_IMMEDIATE;
0376     case IEEE80211_AMPDU_TX_STOP_CONT:
0377         ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
0378         break;
0379     }
0380 
0381     return 0;
0382 }
0383 
0384 static void
0385 mt76_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0386              struct ieee80211_sta *sta)
0387 {
0388     struct mt7601u_dev *dev = hw->priv;
0389     struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
0390     struct ieee80211_sta_rates *rates;
0391     struct ieee80211_tx_rate rate = {};
0392 
0393     rcu_read_lock();
0394     rates = rcu_dereference(sta->rates);
0395 
0396     if (!rates)
0397         goto out;
0398 
0399     rate.idx = rates->rate[0].idx;
0400     rate.flags = rates->rate[0].flags;
0401     mt76_mac_wcid_set_rate(dev, &msta->wcid, &rate);
0402 
0403 out:
0404     rcu_read_unlock();
0405 }
0406 
0407 const struct ieee80211_ops mt7601u_ops = {
0408     .tx = mt7601u_tx,
0409     .start = mt7601u_start,
0410     .stop = mt7601u_stop,
0411     .add_interface = mt7601u_add_interface,
0412     .remove_interface = mt7601u_remove_interface,
0413     .config = mt7601u_config,
0414     .configure_filter = mt76_configure_filter,
0415     .bss_info_changed = mt7601u_bss_info_changed,
0416     .sta_add = mt7601u_sta_add,
0417     .sta_remove = mt7601u_sta_remove,
0418     .sta_notify = mt7601u_sta_notify,
0419     .set_key = mt7601u_set_key,
0420     .conf_tx = mt7601u_conf_tx,
0421     .sw_scan_start = mt7601u_sw_scan,
0422     .sw_scan_complete = mt7601u_sw_scan_complete,
0423     .ampdu_action = mt76_ampdu_action,
0424     .sta_rate_tbl_update = mt76_sta_rate_tbl_update,
0425     .set_rts_threshold = mt7601u_set_rts_threshold,
0426 };