Merge tag 'wireless-drivers-for-davem-2019-03-19' of git://git.kernel.org/pub/scm...
authorDavid S. Miller <davem@davemloft.net>
Tue, 19 Mar 2019 19:45:39 +0000 (12:45 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 19 Mar 2019 19:45:39 +0000 (12:45 -0700)
Kalle Valo says:

====================
wireless-drivers fixes for 5.1

First set of fixes for 5.1. Lots of fixes for mt76 this time.

iwlwifi

* fix warning with do_div()

mt7601u

* avoid using hardware which is supported by mt76

mt76

* more fixes for hweight8() usage

* fix hardware restart for mt76x2

* fix writing txwi on USB devices

* fix (and disable by default) ED/CCA support on 76x2

* fix powersave issues on 7603

* fix return value check for ioremap on 7603

* fix duplicate USB device IDs
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
32 files changed:
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
drivers/net/wireless/mediatek/mt76/mt7603/dma.c
drivers/net/wireless/mediatek/mt76/mt7603/init.c
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
drivers/net/wireless/mediatek/mt76/mt7603/main.c
drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
drivers/net/wireless/mediatek/mt76/mt7603/soc.c
drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
drivers/net/wireless/mediatek/mt76/mt76x02.h
drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c
drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
drivers/net/wireless/mediatek/mt76/mt76x02_util.c
drivers/net/wireless/mediatek/mt76/mt76x2/init.c
drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c
drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
drivers/net/wireless/mediatek/mt76/tx.c
drivers/net/wireless/mediatek/mt76/usb.c
drivers/net/wireless/mediatek/mt7601u/usb.c

index e9822a3ec373929ff520c9dea90c51194adcb69b..94132cfd1f56241b7e9548466c7050541c87e4c5 100644 (file)
@@ -460,9 +460,7 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
 static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index,
                                     struct cfg80211_pmsr_result *res)
 {
-       s64 rtt_avg = res->ftm.rtt_avg * 100;
-
-       do_div(rtt_avg, 6666);
+       s64 rtt_avg = div_s64(res->ftm.rtt_avg * 100, 6666);
 
        IWL_DEBUG_INFO(mvm, "entry %d\n", index);
        IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status);
index 6eedc0ec76616cc55afec8b98f55db1ec27e540b..76629b98c78d78d81d7c61e0cd4771ba8d5f3c39 100644 (file)
@@ -130,6 +130,8 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
 static void
 mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
 {
+       iowrite32(q->desc_dma, &q->regs->desc_base);
+       iowrite32(q->ndesc, &q->regs->ring_size);
        q->head = ioread32(&q->regs->dma_idx);
        q->tail = q->head;
        iowrite32(q->head, &q->regs->cpu_idx);
@@ -180,7 +182,10 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
        else
                mt76_dma_sync_idx(dev, q);
 
-       wake = wake && qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
+       wake = wake && q->stopped &&
+              qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
+       if (wake)
+               q->stopped = false;
 
        if (!q->queued)
                wake_up(&dev->tx_wait);
index a033745adb2f7a738ac576aafd41aa931fcc5ea6..316167404729fdcd8322c71bd5626785822ce90d 100644 (file)
@@ -679,19 +679,15 @@ out:
        return ret;
 }
 
-static void
-mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
-               struct ieee80211_sta *sta)
+void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+                      struct ieee80211_sta *sta)
 {
        struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
-       int idx = wcid->idx;
-       int i;
+       int i, idx = wcid->idx;
 
        rcu_assign_pointer(dev->wcid[idx], NULL);
        synchronize_rcu();
 
-       mutex_lock(&dev->mutex);
-
        if (dev->drv->sta_remove)
                dev->drv->sta_remove(dev, vif, sta);
 
@@ -699,7 +695,15 @@ mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
        for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
                mt76_txq_remove(dev, sta->txq[i]);
        mt76_wcid_free(dev->wcid_mask, idx);
+}
+EXPORT_SYMBOL_GPL(__mt76_sta_remove);
 
+static void
+mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+               struct ieee80211_sta *sta)
+{
+       mutex_lock(&dev->mutex);
+       __mt76_sta_remove(dev, vif, sta);
        mutex_unlock(&dev->mutex);
 }
 
index 5dfb0601f1015c01251d409070ba64bda516db26..bcbfd3c4a44b68199dbc53e0e5ea498cc9e78e89 100644 (file)
@@ -126,6 +126,7 @@ struct mt76_queue {
        int ndesc;
        int queued;
        int buf_size;
+       bool stopped;
 
        u8 buf_offset;
        u8 hw_idx;
@@ -143,6 +144,7 @@ struct mt76_mcu_ops {
                         const struct mt76_reg_pair *rp, int len);
        int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base,
                         struct mt76_reg_pair *rp, int len);
+       int (*mcu_restart)(struct mt76_dev *dev);
 };
 
 struct mt76_queue_ops {
@@ -693,6 +695,8 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                   struct ieee80211_sta *sta,
                   enum ieee80211_sta_state old_state,
                   enum ieee80211_sta_state new_state);
+void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+                      struct ieee80211_sta *sta);
 
 struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
 
index afcd86f735b40e1a508d7fba5c4d38429906c9af..4dcb465095d19e9a0fe88c15a757a59fec802d87 100644 (file)
@@ -135,8 +135,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)
 
 out:
        mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false);
-       if (dev->mt76.q_tx[MT_TXQ_BEACON].queued >
-           __sw_hweight8(dev->beacon_mask))
+       if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > hweight8(dev->beacon_mask))
                dev->beacon_check++;
 }
 
index d69e82c66ab29fb8e8c645de9270ab47a066dd49..b3ae0aaea62a15b51b1ed2c23bc8857f88dec8c9 100644 (file)
@@ -27,12 +27,16 @@ static void
 mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
 {
        __le32 *txd = (__le32 *)skb->data;
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_sta *sta;
        struct mt7603_sta *msta;
        struct mt76_wcid *wcid;
+       void *priv;
        int idx;
        u32 val;
+       u8 tid;
 
-       if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr))
+       if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr))
                goto free;
 
        val = le32_to_cpu(txd[1]);
@@ -46,10 +50,19 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
        if (!wcid)
                goto free;
 
-       msta = container_of(wcid, struct mt7603_sta, wcid);
+       priv = msta = container_of(wcid, struct mt7603_sta, wcid);
        val = le32_to_cpu(txd[0]);
        skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val));
 
+       val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
+       val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT);
+       txd[0] = cpu_to_le32(val);
+
+       sta = container_of(priv, struct ieee80211_sta, drv_priv);
+       hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE];
+       tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+       ieee80211_sta_set_buffered(sta, tid, true);
+
        spin_lock_bh(&dev->ps_lock);
        __skb_queue_tail(&msta->psq, skb);
        if (skb_queue_len(&msta->psq) >= 64) {
index 15cc8f33b34d656d86c745cd10950d2253e864fc..d54dda67d036c19cffce6bc30765c39dc93ee326 100644 (file)
@@ -112,7 +112,7 @@ static void
 mt7603_phy_init(struct mt7603_dev *dev)
 {
        int rx_chains = dev->mt76.antenna_mask;
-       int tx_chains = __sw_hweight8(rx_chains) - 1;
+       int tx_chains = hweight8(rx_chains) - 1;
 
        mt76_rmw(dev, MT_WF_RMAC_RMCR,
                 (MT_WF_RMAC_RMCR_SMPS_MODE |
index 0a0115861b51e500c777daeb805685286ebb4f5a..5e31d7da96fc88e5fab246c61ec1d37a328a8700 100644 (file)
@@ -1072,7 +1072,7 @@ out:
        case MT_PHY_TYPE_HT:
                final_rate_flags |= IEEE80211_TX_RC_MCS;
                final_rate &= GENMASK(5, 0);
-               if (i > 15)
+               if (final_rate > 15)
                        return false;
                break;
        default:
index b10775ed92e65ff72036dc314c061437315c009c..cc0fe0933b2d8043e622f1b513817b6528bbcaae 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/pci.h>
 #include <linux/module.h>
 #include "mt7603.h"
+#include "mac.h"
 #include "eeprom.h"
 
 static int
@@ -385,6 +386,15 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
        mt7603_ps_tx_list(dev, &list);
 }
 
+static void
+mt7603_ps_set_more_data(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr;
+
+       hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE];
+       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+}
+
 static void
 mt7603_release_buffered_frames(struct ieee80211_hw *hw,
                               struct ieee80211_sta *sta,
@@ -399,6 +409,8 @@ mt7603_release_buffered_frames(struct ieee80211_hw *hw,
 
        __skb_queue_head_init(&list);
 
+       mt7603_wtbl_set_ps(dev, msta, false);
+
        spin_lock_bh(&dev->ps_lock);
        skb_queue_walk_safe(&msta->psq, skb, tmp) {
                if (!nframes)
@@ -409,11 +421,15 @@ mt7603_release_buffered_frames(struct ieee80211_hw *hw,
 
                skb_set_queue_mapping(skb, MT_TXQ_PSD);
                __skb_unlink(skb, &msta->psq);
+               mt7603_ps_set_more_data(skb);
                __skb_queue_tail(&list, skb);
                nframes--;
        }
        spin_unlock_bh(&dev->ps_lock);
 
+       if (!skb_queue_empty(&list))
+               ieee80211_sta_eosp(sta);
+
        mt7603_ps_tx_list(dev, &list);
 
        if (nframes)
index 4b0713f1fd5e3da78c83efa05b8f14aabd2fbfc4..d06905ea8cc63f2b9851eb679655007c1e8f7486 100644 (file)
@@ -433,7 +433,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)
 {
        struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
        struct ieee80211_hw *hw = mt76_hw(dev);
-       int n_chains = __sw_hweight8(dev->mt76.antenna_mask);
+       int n_chains = hweight8(dev->mt76.antenna_mask);
        struct {
                u8 control_chan;
                u8 center_chan;
index e13fea80d970d228ef7b99faa69e489f017ffb49..b920be1f5718b75d2f7374b6bbe6a533ebdec9c2 100644 (file)
@@ -23,9 +23,9 @@ mt76_wmac_probe(struct platform_device *pdev)
        }
 
        mem_base = devm_ioremap_resource(&pdev->dev, res);
-       if (!mem_base) {
+       if (IS_ERR(mem_base)) {
                dev_err(&pdev->dev, "Failed to get memory resource\n");
-               return -EINVAL;
+               return PTR_ERR(mem_base);
        }
 
        mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops,
index 0290ba5869a5182ca283db62629d38a2e37b21ef..736f81752b5b488518e1393e6200b67be7bfa87c 100644 (file)
@@ -46,7 +46,7 @@ static const struct mt76_reg_pair common_mac_reg_table[] = {
        { MT_MM20_PROT_CFG,             0x01742004 },
        { MT_MM40_PROT_CFG,             0x03f42084 },
        { MT_TXOP_CTRL_CFG,             0x0000583f },
-       { MT_TX_RTS_CFG,                0x00092b20 },
+       { MT_TX_RTS_CFG,                0x00ffff20 },
        { MT_EXP_ACK_TIME,              0x002400ca },
        { MT_TXOP_HLDR_ET,              0x00000002 },
        { MT_XIFS_TIME_CFG,             0x33a41010 },
index 91718647da0285e40eda86aa97dc98559592732d..e5a06f74a6f701419f703844f4e73fba6307a627 100644 (file)
@@ -229,7 +229,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
        struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
        struct mt76x02_dev *dev;
        struct mt76_dev *mdev;
-       u32 asic_rev, mac_rev;
+       u32 mac_rev;
        int ret;
 
        mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops,
@@ -262,10 +262,14 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
                goto err;
        }
 
-       asic_rev = mt76_rr(dev, MT_ASIC_VERSION);
+       mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
        mac_rev = mt76_rr(dev, MT_MAC_CSR0);
        dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n",
-                asic_rev, mac_rev);
+                mdev->rev, mac_rev);
+       if (!is_mt76x0(dev)) {
+               ret = -ENODEV;
+               goto err;
+       }
 
        /* Note: vendor driver skips this check for MT76X0U */
        if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
index 6915cce5def9342935784c888c477417e26b5c69..07061eb4d1e1b3ef97b7131791af79a0962b6360 100644 (file)
@@ -51,6 +51,7 @@ struct mt76x02_calibration {
        u16 false_cca;
        s8 avg_rssi_all;
        s8 agc_gain_adjust;
+       s8 agc_lowest_gain;
        s8 low_gain;
 
        s8 temp_vco;
@@ -114,8 +115,11 @@ struct mt76x02_dev {
        struct mt76x02_dfs_pattern_detector dfs_pd;
 
        /* edcca monitor */
+       unsigned long ed_trigger_timeout;
        bool ed_tx_blocked;
        bool ed_monitor;
+       u8 ed_monitor_enabled;
+       u8 ed_monitor_learning;
        u8 ed_trigger;
        u8 ed_silent;
        ktime_t ed_time;
@@ -188,6 +192,13 @@ void mt76x02_mac_start(struct mt76x02_dev *dev);
 
 void mt76x02_init_debugfs(struct mt76x02_dev *dev);
 
+static inline bool is_mt76x0(struct mt76x02_dev *dev)
+{
+       return mt76_chip(&dev->mt76) == 0x7610 ||
+              mt76_chip(&dev->mt76) == 0x7630 ||
+              mt76_chip(&dev->mt76) == 0x7650;
+}
+
 static inline bool is_mt76x2(struct mt76x02_dev *dev)
 {
        return mt76_chip(&dev->mt76) == 0x7612 ||
index 7580c5c986ffe5226f4c91feccaf73cd445aabc0..b1d6fd4861e3236b9cb255277c01b9a2f01b1fca 100644 (file)
@@ -116,6 +116,32 @@ static int read_agc(struct seq_file *file, void *data)
        return 0;
 }
 
+static int
+mt76_edcca_set(void *data, u64 val)
+{
+       struct mt76x02_dev *dev = data;
+       enum nl80211_dfs_regions region = dev->dfs_pd.region;
+
+       dev->ed_monitor_enabled = !!val;
+       dev->ed_monitor = dev->ed_monitor_enabled &&
+                         region == NL80211_DFS_ETSI;
+       mt76x02_edcca_init(dev, true);
+
+       return 0;
+}
+
+static int
+mt76_edcca_get(void *data, u64 *val)
+{
+       struct mt76x02_dev *dev = data;
+
+       *val = dev->ed_monitor_enabled;
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_edcca, mt76_edcca_get, mt76_edcca_set,
+                        "%lld\n");
+
 void mt76x02_init_debugfs(struct mt76x02_dev *dev)
 {
        struct dentry *dir;
@@ -127,6 +153,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev)
        debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp);
        debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc);
 
+       debugfs_create_file("edcca", 0400, dir, dev, &fops_edcca);
        debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
        debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat);
        debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir,
index e4649103efd49ab5d77c28f3f01d1aac1c81fc3b..17d12d212d1ba1d0a3eb8f65b9e0ecef42908406 100644 (file)
@@ -885,7 +885,8 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev,
        if (dfs_pd->region != region) {
                tasklet_disable(&dfs_pd->dfs_tasklet);
 
-               dev->ed_monitor = region == NL80211_DFS_ETSI;
+               dev->ed_monitor = dev->ed_monitor_enabled &&
+                                 region == NL80211_DFS_ETSI;
                mt76x02_edcca_init(dev, true);
 
                dfs_pd->region = region;
index 91ff6598eccfb55dfb0fe8e96b4edf6e7941f59f..9ed231abe91676119d751b06cfa995a7f5dd716c 100644 (file)
@@ -67,12 +67,39 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx,
 }
 EXPORT_SYMBOL_GPL(mt76x02_mac_shared_key_setup);
 
+void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx,
+                             struct ieee80211_key_conf *key)
+{
+       enum mt76x02_cipher_type cipher;
+       u8 key_data[32];
+       u32 iv, eiv;
+       u64 pn;
+
+       cipher = mt76x02_mac_get_key_info(key, key_data);
+       iv = mt76_rr(dev, MT_WCID_IV(idx));
+       eiv = mt76_rr(dev, MT_WCID_IV(idx) + 4);
+
+       pn = (u64)eiv << 16;
+       if (cipher == MT_CIPHER_TKIP) {
+               pn |= (iv >> 16) & 0xff;
+               pn |= (iv & 0xff) << 8;
+       } else if (cipher >= MT_CIPHER_AES_CCMP) {
+               pn |= iv & 0xffff;
+       } else {
+               return;
+       }
+
+       atomic64_set(&key->tx_pn, pn);
+}
+
+
 int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx,
                             struct ieee80211_key_conf *key)
 {
        enum mt76x02_cipher_type cipher;
        u8 key_data[32];
        u8 iv_data[8];
+       u64 pn;
 
        cipher = mt76x02_mac_get_key_info(key, key_data);
        if (cipher == MT_CIPHER_NONE && key)
@@ -85,9 +112,22 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx,
        if (key) {
                mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE,
                               !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
+
+               pn = atomic64_read(&key->tx_pn);
+
                iv_data[3] = key->keyidx << 6;
-               if (cipher >= MT_CIPHER_TKIP)
+               if (cipher >= MT_CIPHER_TKIP) {
                        iv_data[3] |= 0x20;
+                       put_unaligned_le32(pn >> 16, &iv_data[4]);
+               }
+
+               if (cipher == MT_CIPHER_TKIP) {
+                       iv_data[0] = (pn >> 8) & 0xff;
+                       iv_data[1] = (iv_data[0] | 0x20) & 0x7f;
+                       iv_data[2] = pn & 0xff;
+               } else if (cipher >= MT_CIPHER_AES_CCMP) {
+                       put_unaligned_le16((pn & 0xffff), &iv_data[0]);
+               }
        }
 
        mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data));
@@ -920,6 +960,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable)
                }
        }
        mt76x02_edcca_tx_enable(dev, true);
+       dev->ed_monitor_learning = true;
 
        /* clear previous CCA timer value */
        mt76_rr(dev, MT_ED_CCA_TIMER);
@@ -929,6 +970,10 @@ EXPORT_SYMBOL_GPL(mt76x02_edcca_init);
 
 #define MT_EDCCA_TH            92
 #define MT_EDCCA_BLOCK_TH      2
+#define MT_EDCCA_LEARN_TH      50
+#define MT_EDCCA_LEARN_CCA     180
+#define MT_EDCCA_LEARN_TIMEOUT (20 * HZ)
+
 static void mt76x02_edcca_check(struct mt76x02_dev *dev)
 {
        ktime_t cur_time;
@@ -951,11 +996,23 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev)
                dev->ed_trigger = 0;
        }
 
-       if (dev->ed_trigger > MT_EDCCA_BLOCK_TH &&
-           !dev->ed_tx_blocked)
+       if (dev->cal.agc_lowest_gain &&
+           dev->cal.false_cca > MT_EDCCA_LEARN_CCA &&
+           dev->ed_trigger > MT_EDCCA_LEARN_TH) {
+               dev->ed_monitor_learning = false;
+               dev->ed_trigger_timeout = jiffies + 20 * HZ;
+       } else if (!dev->ed_monitor_learning &&
+                  time_is_after_jiffies(dev->ed_trigger_timeout)) {
+               dev->ed_monitor_learning = true;
+               mt76x02_edcca_tx_enable(dev, true);
+       }
+
+       if (dev->ed_monitor_learning)
+               return;
+
+       if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && !dev->ed_tx_blocked)
                mt76x02_edcca_tx_enable(dev, false);
-       else if (dev->ed_silent > MT_EDCCA_BLOCK_TH &&
-                dev->ed_tx_blocked)
+       else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && dev->ed_tx_blocked)
                mt76x02_edcca_tx_enable(dev, true);
 }
 
index 6b1f25d2f64c3a931fbf1bd4c695984f9d5bf4ff..caeeef96c42faf74ccf9bb15cc60f4ffe865e9f4 100644 (file)
@@ -177,6 +177,8 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx,
                                 u8 key_idx, struct ieee80211_key_conf *key);
 int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx,
                             struct ieee80211_key_conf *key);
+void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx,
+                             struct ieee80211_key_conf *key);
 void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, u8 vif_idx,
                            u8 *mac);
 void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop);
index 1229f19f2b02c68b4144662e8097333d5133f3ac..daaed1220147ea914c32f13f32f04bd5a360d7fb 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/irq.h>
 
 #include "mt76x02.h"
+#include "mt76x02_mcu.h"
 #include "mt76x02_trace.h"
 
 struct beacon_bc_data {
@@ -418,9 +419,66 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev)
        return i < 4;
 }
 
+static void mt76x02_key_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                            struct ieee80211_sta *sta,
+                            struct ieee80211_key_conf *key, void *data)
+{
+       struct mt76x02_dev *dev = hw->priv;
+       struct mt76_wcid *wcid;
+
+       if (!sta)
+           return;
+
+       wcid = (struct mt76_wcid *) sta->drv_priv;
+
+       if (wcid->hw_key_idx != key->keyidx || wcid->sw_iv)
+           return;
+
+       mt76x02_mac_wcid_sync_pn(dev, wcid->idx, key);
+}
+
+static void mt76x02_reset_state(struct mt76x02_dev *dev)
+{
+       int i;
+
+       lockdep_assert_held(&dev->mt76.mutex);
+
+       clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
+
+       rcu_read_lock();
+       ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL);
+       rcu_read_unlock();
+
+       for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) {
+               struct ieee80211_sta *sta;
+               struct ieee80211_vif *vif;
+               struct mt76x02_sta *msta;
+               struct mt76_wcid *wcid;
+               void *priv;
+
+               wcid = rcu_dereference_protected(dev->mt76.wcid[i],
+                                       lockdep_is_held(&dev->mt76.mutex));
+               if (!wcid)
+                       continue;
+
+               priv = msta = container_of(wcid, struct mt76x02_sta, wcid);
+               sta = container_of(priv, struct ieee80211_sta, drv_priv);
+
+               priv = msta->vif;
+               vif = container_of(priv, struct ieee80211_vif, drv_priv);
+
+               __mt76_sta_remove(&dev->mt76, vif, sta);
+               memset(msta, 0, sizeof(*msta));
+       }
+
+       dev->vif_mask = 0;
+       dev->beacon_mask = 0;
+}
+
 static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 {
        u32 mask = dev->mt76.mmio.irqmask;
+       bool restart = dev->mt76.mcu_ops->mcu_restart;
        int i;
 
        ieee80211_stop_queues(dev->mt76.hw);
@@ -434,6 +492,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 
        mutex_lock(&dev->mt76.mutex);
 
+       if (restart)
+               mt76x02_reset_state(dev);
+
        if (dev->beacon_mask)
                mt76_clear(dev, MT_BEACON_TIME_CFG,
                           MT_BEACON_TIME_CFG_BEACON_TX |
@@ -452,20 +513,21 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
        /* let fw reset DMA */
        mt76_set(dev, 0x734, 0x3);
 
+       if (restart)
+               dev->mt76.mcu_ops->mcu_restart(&dev->mt76);
+
        for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++)
                mt76_queue_tx_cleanup(dev, i, true);
 
        for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
                mt76_queue_rx_reset(dev, i);
 
-       mt76_wr(dev, MT_MAC_SYS_CTRL,
-               MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
-       mt76_set(dev, MT_WPDMA_GLO_CFG,
-                MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN);
+       mt76x02_mac_start(dev);
+
        if (dev->ed_monitor)
                mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
 
-       if (dev->beacon_mask)
+       if (dev->beacon_mask && !restart)
                mt76_set(dev, MT_BEACON_TIME_CFG,
                         MT_BEACON_TIME_CFG_BEACON_TX |
                         MT_BEACON_TIME_CFG_TBTT_EN);
@@ -486,9 +548,13 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
                napi_schedule(&dev->mt76.napi[i]);
        }
 
-       ieee80211_wake_queues(dev->mt76.hw);
-
-       mt76_txq_schedule_all(&dev->mt76);
+       if (restart) {
+               mt76x02_mcu_function_select(dev, Q_SELECT, 1);
+               ieee80211_restart_hw(dev->mt76.hw);
+       } else {
+               ieee80211_wake_queues(dev->mt76.hw);
+               mt76_txq_schedule_all(&dev->mt76);
+       }
 }
 
 static void mt76x02_check_tx_hang(struct mt76x02_dev *dev)
index a020c757ba5c6c59fba0463d01f5774a916e4339..a54b63a96eaefa24268f28573f1123c30ee6b9d5 100644 (file)
@@ -194,6 +194,8 @@ bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev *dev)
                ret = true;
        }
 
+       dev->cal.agc_lowest_gain = dev->cal.agc_gain_adjust >= limit;
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain);
index 43f07461c8d39b6045388c8bbe59b1d2b0fcd6e8..6fb52b596d421753ff24f247225136b30c15150b 100644 (file)
@@ -85,8 +85,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 
        mt76x02_insert_hdr_pad(skb);
 
-       txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
+       txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi));
        mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
+       skb_push(skb, sizeof(struct mt76x02_txwi));
 
        pid = mt76_tx_status_skb_add(mdev, wcid, skb);
        txwi->pktid = pid;
index a48c261b0c634bca601f8d9fcd496b99a5bc2fa7..cd072ac614f76847b86618a4f40c87af171f5147 100644 (file)
@@ -237,6 +237,8 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
        int idx = 0;
 
+       memset(msta, 0, sizeof(*msta));
+
        idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid));
        if (idx < 0)
                return -ENOSPC;
@@ -274,6 +276,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
        struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
        struct mt76_txq *mtxq;
 
+       memset(mvif, 0, sizeof(*mvif));
+
        mvif->idx = idx;
        mvif->group_wcid.idx = MT_VIF_WCID(idx);
        mvif->group_wcid.hw_key_idx = -1;
@@ -289,6 +293,12 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        struct mt76x02_dev *dev = hw->priv;
        unsigned int idx = 0;
 
+       /* Allow to change address in HW if we create first interface. */
+       if (!dev->vif_mask &&
+           (((vif->addr[0] ^ dev->mt76.macaddr[0]) & ~GENMASK(4, 1)) ||
+            memcmp(vif->addr + 1, dev->mt76.macaddr + 1, ETH_ALEN - 1)))
+               mt76x02_mac_setaddr(dev, vif->addr);
+
        if (vif->addr[0] & BIT(1))
                idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7);
 
@@ -311,10 +321,6 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        if (dev->vif_mask & BIT(idx))
                return -EBUSY;
 
-       /* Allow to change address in HW if we create first interface. */
-       if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr))
-                mt76x02_mac_setaddr(dev, vif->addr);
-
        dev->vif_mask |= BIT(idx);
 
        mt76x02_vif_init(dev, vif, idx);
index f8534362e2c8cdf7edf9b03d5e2118d885d5ca6f..a30ef2c5a9db0433cbb696f6ab6f3e8b1811cb5d 100644 (file)
@@ -106,7 +106,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev)
                { MT_TX_SW_CFG1,                0x00010000 },
                { MT_TX_SW_CFG2,                0x00000000 },
                { MT_TXOP_CTRL_CFG,             0x0400583f },
-               { MT_TX_RTS_CFG,                0x00100020 },
+               { MT_TX_RTS_CFG,                0x00ffff20 },
                { MT_TX_TIMEOUT_CFG,            0x000a2290 },
                { MT_TX_RETRY_CFG,              0x47f01f0f },
                { MT_EXP_ACK_TIME,              0x002c00dc },
index 6c619f1c65c9cbfbbdf9241dc340c448826ab228..d7abe3d73badbbce7100781ece4b5c91407bc0dd 100644 (file)
@@ -71,6 +71,7 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
 
 void mt76x2_cleanup(struct mt76x02_dev *dev);
 
+int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard);
 void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable);
 void mt76x2_init_txpower(struct mt76x02_dev *dev,
                         struct ieee80211_supported_band *sband);
index 984d9c4c2e1a8ac9bfb435ef8de97898cb720b4d..d3927a13e92e91068344e431176a3b42ef6ff444 100644 (file)
@@ -77,7 +77,7 @@ mt76x2_fixup_xtal(struct mt76x02_dev *dev)
        }
 }
 
-static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
+int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
 {
        const u8 *macaddr = dev->mt76.macaddr;
        u32 val;
index 03e24ae7f66c7c8953e7308a1bac304ff294fb1b..605dc66ae83be45d956c0483e9688a8482f442c8 100644 (file)
@@ -165,9 +165,30 @@ error:
        return -ENOENT;
 }
 
+static int
+mt76pci_mcu_restart(struct mt76_dev *mdev)
+{
+       struct mt76x02_dev *dev;
+       int ret;
+
+       dev = container_of(mdev, struct mt76x02_dev, mt76);
+
+       mt76x02_mcu_cleanup(dev);
+       mt76x2_mac_reset(dev, true);
+
+       ret = mt76pci_load_firmware(dev);
+       if (ret)
+               return ret;
+
+       mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
+
+       return 0;
+}
+
 int mt76x2_mcu_init(struct mt76x02_dev *dev)
 {
        static const struct mt76_mcu_ops mt76x2_mcu_ops = {
+               .mcu_restart = mt76pci_mcu_restart,
                .mcu_send_msg = mt76x02_mcu_msg_send,
        };
        int ret;
index 1848e8ab2e21cfb6332fd17259986d6b932dbff6..769a9b9720442c5d303e9a65519a8fe1de166089 100644 (file)
@@ -260,10 +260,15 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev)
        gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust;
        gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust;
 
-       if (dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40)
+       val = 0x1836 << 16;
+       if (!mt76x2_has_ext_lna(dev) &&
+           dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40)
                val = 0x1e42 << 16;
-       else
-               val = 0x1836 << 16;
+
+       if (mt76x2_has_ext_lna(dev) &&
+           dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ &&
+           dev->mt76.chandef.width < NL80211_CHAN_WIDTH_40)
+               val = 0x0f36 << 16;
 
        val |= 0xf8;
 
@@ -280,6 +285,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
 {
        u8 *gain = dev->cal.agc_gain_init;
        u8 low_gain_delta, gain_delta;
+       u32 agc_35, agc_37;
        bool gain_change;
        int low_gain;
        u32 val;
@@ -318,6 +324,16 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
        else
                low_gain_delta = 14;
 
+       agc_37 = 0x2121262c;
+       if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ)
+               agc_35 = 0x11111516;
+       else if (low_gain == 2)
+               agc_35 = agc_37 = 0x08080808;
+       else if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80)
+               agc_35 = 0x10101014;
+       else
+               agc_35 = 0x11111116;
+
        if (low_gain == 2) {
                mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990);
                mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808);
@@ -326,15 +342,13 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
                dev->cal.agc_gain_adjust = 0;
        } else {
                mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991);
-               if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80)
-                       mt76_wr(dev, MT_BBP(AGC, 35), 0x10101014);
-               else
-                       mt76_wr(dev, MT_BBP(AGC, 35), 0x11111116);
-               mt76_wr(dev, MT_BBP(AGC, 37), 0x2121262C);
                gain_delta = 0;
                dev->cal.agc_gain_adjust = low_gain_delta;
        }
 
+       mt76_wr(dev, MT_BBP(AGC, 35), agc_35);
+       mt76_wr(dev, MT_BBP(AGC, 37), agc_37);
+
        dev->cal.agc_gain_cur[0] = gain[0] - gain_delta;
        dev->cal.agc_gain_cur[1] = gain[1] - gain_delta;
        mt76x2_phy_set_gain_val(dev);
index ddb6b2c48e01283a8041620fdbc46542de8d04c7..ac0f13d4629963cea77e5ab113caf3e11a33275a 100644 (file)
 #include "mt76x2u.h"
 
 static const struct usb_device_id mt76x2u_device_table[] = {
-       { USB_DEVICE(0x0e8d, 0x7612) }, /* Alfa AWUS036ACM */
        { USB_DEVICE(0x0b05, 0x1833) }, /* Asus USB-AC54 */
        { USB_DEVICE(0x0b05, 0x17eb) }, /* Asus USB-AC55 */
        { USB_DEVICE(0x0b05, 0x180b) }, /* Asus USB-N53 B1 */
-       { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USB-AC1200 */
+       { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */
        { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
        { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
        { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */
@@ -66,6 +65,10 @@ static int mt76x2u_probe(struct usb_interface *intf,
 
        mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
        dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
+       if (!is_mt76x2(dev)) {
+               err = -ENODEV;
+               goto err;
+       }
 
        err = mt76x2u_register_device(dev);
        if (err < 0)
index 5e84b4535cb1456c22bbf883d79c9d44c62da438..3b82345756ea90d3cc93f71946c2ec6cb7e81110 100644 (file)
@@ -93,7 +93,6 @@ int mt76x2u_mac_reset(struct mt76x02_dev *dev)
        mt76_wr(dev, MT_TX_LINK_CFG, 0x1020);
        mt76_wr(dev, MT_AUTO_RSP_CFG, 0x13);
        mt76_wr(dev, MT_MAX_LEN_CFG, 0x2f00);
-       mt76_wr(dev, MT_TX_RTS_CFG, 0x92b20);
 
        mt76_wr(dev, MT_WMM_AIFSN, 0x2273);
        mt76_wr(dev, MT_WMM_CWMIN, 0x2344);
index 5a349fe3e576f606ec2fb1997ed8a394d54d7b3f..2585df5123350ba8adf52cf14ef6133de7e03f77 100644 (file)
@@ -289,8 +289,11 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
        dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
        dev->queue_ops->kick(dev, q);
 
-       if (q->queued > q->ndesc - 8)
+       if (q->queued > q->ndesc - 8 && !q->stopped) {
                ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb));
+               q->stopped = true;
+       }
+
        spin_unlock_bh(&q->lock);
 }
 EXPORT_SYMBOL_GPL(mt76_tx);
@@ -374,7 +377,10 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
        if (last_skb) {
                mt76_queue_ps_skb(dev, sta, last_skb, true);
                dev->queue_ops->kick(dev, hwq);
+       } else {
+               ieee80211_sta_eosp(sta);
        }
+
        spin_unlock_bh(&hwq->lock);
 }
 EXPORT_SYMBOL_GPL(mt76_release_buffered_frames);
@@ -577,6 +583,9 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
        struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv;
        struct mt76_queue *hwq = mtxq->hwq;
 
+       if (!test_bit(MT76_STATE_RUNNING, &dev->state))
+               return;
+
        spin_lock_bh(&hwq->lock);
        if (list_empty(&mtxq->list))
                list_add_tail(&mtxq->list, &hwq->swq);
index ae6ada370597a6f0ebfd3b7d69bb583ecf8759ef..4c1abd4924054c6f377ca062ad98ca5bb8446dc7 100644 (file)
@@ -655,7 +655,11 @@ static void mt76u_tx_tasklet(unsigned long data)
                        spin_lock_bh(&q->lock);
                }
                mt76_txq_schedule(dev, q);
-               wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
+
+               wake = q->stopped && q->queued < q->ndesc - 8;
+               if (wake)
+                       q->stopped = false;
+
                if (!q->queued)
                        wake_up(&dev->tx_wait);
 
index d8b7863f79261a3275b6641ffdf7607e23fdd206..6ae7f14dc9bf936ec3ae34f9f4d4f1ee67de6646 100644 (file)
@@ -303,6 +303,10 @@ static int mt7601u_probe(struct usb_interface *usb_intf,
        mac_rev = mt7601u_rr(dev, MT_MAC_CSR0);
        dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n",
                 asic_rev, mac_rev);
+       if ((asic_rev >> 16) != 0x7601) {
+               ret = -ENODEV;
+               goto err;
+       }
 
        /* Note: vendor driver skips this check for MT7601U */
        if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))