summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dma.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_init.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mac.c16
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_main.c36
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_tx.c6
8 files changed, 65 insertions, 18 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index aa0880bbea7f..f88d9a15210a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -129,6 +129,7 @@ struct mt76_wcid {
bool tx_rate_set;
u8 tx_rate_nss;
s8 max_txpwr_adj;
+ bool sw_iv;
};
struct mt76_txq {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
index 5b452a596016..f936dc9a5476 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
@@ -460,8 +460,8 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
{
struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
- tasklet_kill(&dev->dfs_pd.dfs_tasklet);
- if (chandef->chan->flags & IEEE80211_CHAN_RADAR) {
+ if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
+ dev->dfs_pd.region != NL80211_DFS_UNSET) {
mt76x2_dfs_set_bbp_params(dev);
/* enable debug mode */
mt76x2_dfs_set_capture_mode_ctrl(dev, true);
@@ -491,3 +491,16 @@ void mt76x2_dfs_init_detector(struct mt76x2_dev *dev)
(unsigned long)dev);
}
+void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
+ enum nl80211_dfs_regions region)
+{
+ struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+
+ if (dfs_pd->region != region) {
+ tasklet_disable(&dfs_pd->dfs_tasklet);
+ dfs_pd->region = region;
+ mt76x2_dfs_init_params(dev);
+ tasklet_enable(&dfs_pd->dfs_tasklet);
+ }
+}
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
index 9ac69b6a116d..8dbc783cc6bc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
@@ -76,5 +76,7 @@ struct mt76x2_dfs_pattern_detector {
void mt76x2_dfs_init_params(struct mt76x2_dev *dev);
void mt76x2_dfs_init_detector(struct mt76x2_dev *dev);
void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev);
+void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
+ enum nl80211_dfs_regions region);
#endif /* __MT76x2_DFS_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c b/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
index 0a3f729a7156..fd1ec4743e0b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
@@ -55,6 +55,7 @@ mt76x2_init_tx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
q->regs = dev->mt76.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
q->ndesc = n_desc;
+ q->hw_idx = idx;
ret = mt76_queue_alloc(dev, q);
if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
index 4373a2ba5143..7b4851481dd6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
@@ -614,6 +614,8 @@ void mt76x2_stop_hardware(struct mt76x2_dev *dev)
void mt76x2_cleanup(struct mt76x2_dev *dev)
{
+ tasklet_disable(&dev->dfs_pd.dfs_tasklet);
+ tasklet_disable(&dev->pre_tbtt_tasklet);
mt76x2_stop_hardware(dev);
mt76x2_dma_cleanup(dev);
mt76x2_mcu_cleanup(dev);
@@ -652,7 +654,7 @@ static void mt76x2_regd_notifier(struct wiphy *wiphy,
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt76x2_dev *dev = hw->priv;
- dev->dfs_pd.region = request->dfs_region;
+ mt76x2_dfs_set_domain(dev, request->dfs_region);
}
#define CCK_RATE(_idx, _rate) { \
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
index f7c0df0759f7..a7416a01baa4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
@@ -171,10 +171,12 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ struct ieee80211_key_conf *key = info->control.hw_key;
u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
u16 txwi_flags = 0;
u8 nss;
s8 txpwr_adj, max_txpwr_adj;
+ u8 ccmp_pn[8];
memset(txwi, 0, sizeof(*txwi));
@@ -185,6 +187,20 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
txwi->pktid = 1;
+ if (wcid && wcid->sw_iv && key) {
+ u64 pn = atomic64_inc_return(&key->tx_pn);
+ ccmp_pn[0] = pn;
+ ccmp_pn[1] = pn >> 8;
+ ccmp_pn[2] = 0;
+ ccmp_pn[3] = 0x20 | (key->keyidx << 6);
+ ccmp_pn[4] = pn >> 16;
+ ccmp_pn[5] = pn >> 24;
+ ccmp_pn[6] = pn >> 32;
+ ccmp_pn[7] = pn >> 40;
+ txwi->iv = *((u32 *) &ccmp_pn[0]);
+ txwi->eiv = *((u32 *) &ccmp_pn[1]);
+ }
+
spin_lock_bh(&dev->mt76.lock);
if (wcid && (rate->idx < 0 || !rate->count)) {
txwi->rate = wcid->tx_rate;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
index 79915cbee3f0..aa5fbb64e218 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
@@ -127,6 +127,7 @@ mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
mt76_set_channel(&dev->mt76);
tasklet_disable(&dev->pre_tbtt_tasklet);
+ tasklet_disable(&dev->dfs_pd.dfs_tasklet);
cancel_delayed_work_sync(&dev->cal_work);
mt76x2_mac_stop(dev, true);
@@ -139,6 +140,7 @@ mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
mt76x2_dfs_init_params(dev);
mt76x2_mac_resume(dev);
+ tasklet_enable(&dev->dfs_pd.dfs_tasklet);
tasklet_enable(&dev->pre_tbtt_tasklet);
return ret;
@@ -355,9 +357,15 @@ mt76x2_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == SET_KEY) {
key->hw_key_idx = wcid->idx;
wcid->hw_key_idx = idx;
+ if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ wcid->sw_iv = true;
+ }
} else {
- if (idx == wcid->hw_key_idx)
+ if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1;
+ wcid->sw_iv = true;
+ }
key = NULL;
}
@@ -380,9 +388,11 @@ mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt76x2_dev *dev = hw->priv;
- u8 cw_min = 5, cw_max = 10;
+ u8 cw_min = 5, cw_max = 10, qid;
u32 val;
+ qid = dev->mt76.q_tx[queue].hw_idx;
+
if (params->cw_min)
cw_min = fls(params->cw_min);
if (params->cw_max)
@@ -392,26 +402,26 @@ mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
FIELD_PREP(MT_EDCA_CFG_AIFSN, params->aifs) |
FIELD_PREP(MT_EDCA_CFG_CWMIN, cw_min) |
FIELD_PREP(MT_EDCA_CFG_CWMAX, cw_max);
- mt76_wr(dev, MT_EDCA_CFG_AC(queue), val);
+ mt76_wr(dev, MT_EDCA_CFG_AC(qid), val);
- val = mt76_rr(dev, MT_WMM_TXOP(queue));
- val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue));
- val |= params->txop << MT_WMM_TXOP_SHIFT(queue);
- mt76_wr(dev, MT_WMM_TXOP(queue), val);
+ val = mt76_rr(dev, MT_WMM_TXOP(qid));
+ val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(qid));
+ val |= params->txop << MT_WMM_TXOP_SHIFT(qid);
+ mt76_wr(dev, MT_WMM_TXOP(qid), val);
val = mt76_rr(dev, MT_WMM_AIFSN);
- val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue));
- val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue);
+ val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(qid));
+ val |= params->aifs << MT_WMM_AIFSN_SHIFT(qid);
mt76_wr(dev, MT_WMM_AIFSN, val);
val = mt76_rr(dev, MT_WMM_CWMIN);
- val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue));
- val |= cw_min << MT_WMM_CWMIN_SHIFT(queue);
+ val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(qid));
+ val |= cw_min << MT_WMM_CWMIN_SHIFT(qid);
mt76_wr(dev, MT_WMM_CWMIN, val);
val = mt76_rr(dev, MT_WMM_CWMAX);
- val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue));
- val |= cw_max << MT_WMM_CWMAX_SHIFT(queue);
+ val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(qid));
+ val |= cw_max << MT_WMM_CWMAX_SHIFT(qid);
mt76_wr(dev, MT_WMM_CWMAX, val);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
index 1a32e1fb8743..534e4bf9a34c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
@@ -36,7 +36,9 @@ void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
msta = (struct mt76x2_sta *) control->sta->drv_priv;
wcid = &msta->wcid;
- } else if (vif) {
+ }
+
+ if (vif || (!info->control.hw_key && wcid->hw_key_idx != -1)) {
struct mt76x2_vif *mvif;
mvif = (struct mt76x2_vif *) vif->drv_priv;
@@ -166,7 +168,7 @@ int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
*tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
MT_TXD_INFO_80211;
- if (!wcid || wcid->hw_key_idx == 0xff)
+ if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv)
*tx_info |= MT_TXD_INFO_WIV;
return 0;