aboutsummaryrefslogtreecommitdiff
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/debugfs.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c43
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_init.c38
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mac.c30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_main.c23
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_phy.c30
8 files changed, 117 insertions, 63 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c
index 7c3612aaa8c4..c121b502a462 100644
--- a/drivers/net/wireless/mediatek/mt76/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/debugfs.c
@@ -33,7 +33,8 @@ mt76_reg_get(void *data, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set,
+ "0x%08llx\n");
static int
mt76_queues_read(struct seq_file *s, void *data)
@@ -65,8 +66,8 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
debugfs_create_u8("led_pin", S_IRUSR | S_IWUSR, dir, &dev->led_pin);
debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
- debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
- &fops_regval);
+ debugfs_create_file_unsafe("regval", S_IRUSR | S_IWUSR, dir, dev,
+ &fops_regval);
debugfs_create_blob("eeprom", S_IRUSR, dir, &dev->eeprom);
if (dev->otp.data)
debugfs_create_blob("otp", S_IRUSR, dir, &dev->otp);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
index 440b7e7d73a9..9c9bf3e785ba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
@@ -425,12 +425,13 @@ mt76x2_rate_power_val(u8 val)
return mt76x2_sign_extend_optional(val, 7);
}
-void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t)
+void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
+ struct ieee80211_channel *chan)
{
bool is_5ghz;
u16 val;
- is_5ghz = dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ;
+ is_5ghz = chan->band == NL80211_BAND_5GHZ;
memset(t, 0, sizeof(*t));
@@ -482,11 +483,22 @@ void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t)
t->vht[8] = t->vht[9] = mt76x2_rate_power_val(val >> 8);
}
+int mt76x2_get_max_rate_power(struct mt76_rate_power *r)
+{
+ int i;
+ s8 ret = 0;
+
+ for (i = 0; i < sizeof(r->all); i++)
+ ret = max(ret, r->all[i]);
+
+ return ret;
+}
+
static void
mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
- int chain, int offset)
+ struct ieee80211_channel *chan, int chain, int offset)
{
- int channel = dev->mt76.chandef.chan->hw_value;
+ int channel = chan->hw_value;
int delta_idx;
u8 data[6];
u16 val;
@@ -511,9 +523,9 @@ mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
static void
mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
- int chain, int offset)
+ struct ieee80211_channel *chan, int chain, int offset)
{
- int channel = dev->mt76.chandef.chan->hw_value;
+ int channel = chan->hw_value;
enum mt76x2_cal_channel_group group;
int delta_idx;
u16 val;
@@ -524,7 +536,7 @@ mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
if (channel >= 192)
delta_idx = 4;
- else if (channel >= 484)
+ else if (channel >= 184)
delta_idx = 3;
else if (channel < 44)
delta_idx = 3;
@@ -559,7 +571,8 @@ mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
}
void mt76x2_get_power_info(struct mt76x2_dev *dev,
- struct mt76x2_tx_power_info *t)
+ struct mt76x2_tx_power_info *t,
+ struct ieee80211_channel *chan)
{
u16 bw40, bw80;
@@ -568,13 +581,17 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev,
bw40 = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
bw80 = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80);
- if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) {
+ if (chan->band == NL80211_BAND_5GHZ) {
bw40 >>= 8;
- mt76x2_get_power_info_5g(dev, t, 0, MT_EE_TX_POWER_0_START_5G);
- mt76x2_get_power_info_5g(dev, t, 1, MT_EE_TX_POWER_1_START_5G);
+ mt76x2_get_power_info_5g(dev, t, chan, 0,
+ MT_EE_TX_POWER_0_START_5G);
+ mt76x2_get_power_info_5g(dev, t, chan, 1,
+ MT_EE_TX_POWER_1_START_5G);
} else {
- mt76x2_get_power_info_2g(dev, t, 0, MT_EE_TX_POWER_0_START_2G);
- mt76x2_get_power_info_2g(dev, t, 1, MT_EE_TX_POWER_1_START_2G);
+ mt76x2_get_power_info_2g(dev, t, chan, 0,
+ MT_EE_TX_POWER_0_START_2G);
+ mt76x2_get_power_info_2g(dev, t, chan, 1,
+ MT_EE_TX_POWER_1_START_2G);
}
if (mt76x2_tssi_enabled(dev) || !field_valid(t->target_power))
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h
index 063d6c8451c9..d79122728dca 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h
@@ -146,9 +146,12 @@ mt76x2_eeprom_get(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field)
return get_unaligned_le16(dev->mt76.eeprom.data + field);
}
-void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t);
+void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
+ struct ieee80211_channel *chan);
+int mt76x2_get_max_rate_power(struct mt76_rate_power *r);
void mt76x2_get_power_info(struct mt76x2_dev *dev,
- struct mt76x2_tx_power_info *t);
+ struct mt76x2_tx_power_info *t,
+ struct ieee80211_channel *chan);
int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t);
bool mt76x2_ext_pa_enabled(struct mt76x2_dev *dev, enum nl80211_band band);
void mt76x2_read_rx_gain(struct mt76x2_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
index d3f03a8aee90..4373a2ba5143 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
@@ -308,8 +308,6 @@ int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard)
for (i = 0; i < 16; i++)
mt76_rr(dev, MT_TX_STAT_FIFO);
- mt76_set(dev, MT_MAC_APC_BSSID_H(0), MT_MAC_APC_BSSID0_H_EN);
-
mt76_wr(dev, MT_CH_TIME_CFG,
MT_CH_TIME_CFG_TIMER_EN |
MT_CH_TIME_CFG_TX_AS_BUSY |
@@ -586,6 +584,8 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
if (ret)
return ret;
+ dev->rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
+
ret = mt76x2_dma_init(dev);
if (ret)
return ret;
@@ -600,7 +600,6 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
return ret;
mt76x2_mac_stop(dev, false);
- dev->rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
return 0;
}
@@ -760,6 +759,37 @@ static void mt76x2_led_set_brightness(struct led_classdev *led_cdev,
mt76x2_led_set_config(mt76, 0xff, 0);
}
+static void
+mt76x2_init_txpower(struct mt76x2_dev *dev,
+ struct ieee80211_supported_band *sband)
+{
+ struct ieee80211_channel *chan;
+ struct mt76x2_tx_power_info txp;
+ struct mt76_rate_power t = {};
+ int target_power;
+ int i;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ chan = &sband->channels[i];
+
+ mt76x2_get_power_info(dev, &txp, chan);
+
+ target_power = max_t(int, (txp.chain[0].target_power +
+ txp.chain[0].delta),
+ (txp.chain[1].target_power +
+ txp.chain[1].delta));
+
+ mt76x2_get_rate_power(dev, &t, chan);
+
+ chan->max_power = mt76x2_get_max_rate_power(&t) +
+ target_power;
+ chan->max_power /= 2;
+
+ /* convert to combined output power on 2x2 devices */
+ chan->max_power += 3;
+ }
+}
+
int mt76x2_register_device(struct mt76x2_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
@@ -828,6 +858,8 @@ int mt76x2_register_device(struct mt76x2_dev *dev)
goto fail;
mt76x2_init_debugfs(dev);
+ mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband);
+ mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
index 39fc1d7b65ce..f7c0df0759f7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
@@ -28,7 +28,7 @@ void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr)
get_unaligned_le16(addr + 4));
}
-static void
+static int
mt76x2_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
{
u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
@@ -42,7 +42,7 @@ mt76x2_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
idx += 4;
status->rate_idx = idx;
- return;
+ return 0;
case MT_PHY_TYPE_CCK:
if (idx >= 8) {
idx -= 8;
@@ -53,7 +53,7 @@ mt76x2_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
idx = 0;
status->rate_idx = idx;
- return;
+ return 0;
case MT_PHY_TYPE_HT_GF:
status->enc_flags |= RX_ENC_FLAG_HT_GF;
/* fall through */
@@ -67,8 +67,7 @@ mt76x2_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1;
break;
default:
- WARN_ON(1);
- return;
+ return -EINVAL;
}
if (rate & MT_RXWI_RATE_LDPC)
@@ -92,6 +91,8 @@ mt76x2_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
default:
break;
}
+
+ return 0;
}
static __le16
@@ -185,7 +186,7 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
txwi->pktid = 1;
spin_lock_bh(&dev->mt76.lock);
- if (rate->idx < 0 || !rate->count) {
+ if (wcid && (rate->idx < 0 || !rate->count)) {
txwi->rate = wcid->tx_rate;
max_txpwr_adj = wcid->max_txpwr_adj;
nss = wcid->tx_rate_nss;
@@ -272,12 +273,10 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
status->freq = dev->mt76.chandef.chan->center_freq;
status->band = dev->mt76.chandef.chan->band;
- mt76x2_mac_process_rate(status, rate);
-
- return 0;
+ return mt76x2_mac_process_rate(status, rate);
}
-static void
+static int
mt76x2_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
enum nl80211_band band)
{
@@ -293,13 +292,13 @@ mt76x2_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
idx += 4;
txrate->idx = idx;
- return;
+ return 0;
case MT_PHY_TYPE_CCK:
if (idx >= 8)
idx -= 8;
txrate->idx = idx;
- return;
+ return 0;
case MT_PHY_TYPE_HT_GF:
txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
/* fall through */
@@ -312,8 +311,7 @@ mt76x2_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
txrate->idx = idx;
break;
default:
- WARN_ON(1);
- return;
+ return -EINVAL;
}
switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) {
@@ -326,12 +324,14 @@ mt76x2_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
txrate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH;
break;
default:
- WARN_ON(1);
+ return -EINVAL;
break;
}
if (rate & MT_RXWI_RATE_SGI)
txrate->flags |= IEEE80211_TX_RC_SHORT_GI;
+
+ return 0;
}
static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
index 2cef48edb275..79915cbee3f0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
@@ -83,7 +83,6 @@ mt76x2_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
struct mt76x2_dev *dev = hw->priv;
struct mt76x2_vif *mvif = (struct mt76x2_vif *) vif->drv_priv;
unsigned int idx = 0;
- int ret = 0;
if (vif->addr[0] & BIT(1))
idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7);
@@ -109,7 +108,7 @@ mt76x2_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mvif->group_wcid.hw_key_idx = -1;
mt76x2_txq_init(dev, vif->txq);
- return ret;
+ return 0;
}
static void
@@ -153,9 +152,21 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&dev->mutex);
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
+ dev->rxfilter |= MT_RX_FILTR_CFG_PROMISC;
+ else
+ dev->rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
+
+ mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
+ }
+
if (changed & IEEE80211_CONF_CHANGE_POWER) {
dev->txpower_conf = hw->conf.power_level * 2;
+ /* convert to per-chain power for 2x2 devices */
+ dev->txpower_conf -= 6;
+
if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) {
mt76x2_phy_set_txpower(dev);
mt76x2_tx_set_txpwr_auto(dev, dev->txpower_conf);
@@ -438,6 +449,10 @@ mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
struct mt76x2_dev *dev = hw->priv;
*dbm = dev->txpower_cur / 2;
+
+ /* convert from per-chain power to combined output on 2x2 devices */
+ *dbm += 3;
+
return 0;
}
@@ -450,13 +465,15 @@ mt76x2_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76x2_dev *dev = hw->priv;
struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
struct ieee80211_txq *txq = sta->txq[params->tid];
- struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv;
u16 tid = params->tid;
u16 *ssn = &params->ssn;
+ struct mt76_txq *mtxq;
if (!txq)
return -EINVAL;
+ mtxq = (struct mt76_txq *)txq->drv_priv;
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
index d45737ee1412..15820b11f9db 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
@@ -45,6 +45,8 @@ static struct sk_buff *mt76x2_mcu_msg_alloc(const void *data, int len)
struct sk_buff *skb;
skb = alloc_skb(len, GFP_KERNEL);
+ if (!skb)
+ return NULL;
memcpy(skb_put(skb, len), data, len);
return skb;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
index 126497172284..5b742749d5de 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
@@ -102,26 +102,15 @@ mt76x2_limit_rate_power(struct mt76_rate_power *r, int limit)
r->all[i] = limit;
}
-static int
-mt76x2_get_max_power(struct mt76_rate_power *r)
-{
- int i;
- s8 ret = 0;
-
- for (i = 0; i < sizeof(r->all); i++)
- ret = max(ret, r->all[i]);
-
- return ret;
-}
-
void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
{
enum nl80211_chan_width width = dev->mt76.chandef.width;
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
struct mt76x2_tx_power_info txp;
int txp_0, txp_1, delta = 0;
struct mt76_rate_power t = {};
- mt76x2_get_power_info(dev, &txp);
+ mt76x2_get_power_info(dev, &txp, chan);
if (width == NL80211_CHAN_WIDTH_40)
delta = txp.delta_bw40;
@@ -131,11 +120,11 @@ void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
if (txp.target_power > dev->txpower_conf)
delta -= txp.target_power - dev->txpower_conf;
- mt76x2_get_rate_power(dev, &t);
+ mt76x2_get_rate_power(dev, &t, chan);
mt76x2_add_rate_power_offset(&t, txp.chain[0].target_power +
txp.chain[0].delta);
mt76x2_limit_rate_power(&t, dev->txpower_conf);
- dev->txpower_cur = mt76x2_get_max_power(&t);
+ dev->txpower_cur = mt76x2_get_max_rate_power(&t);
mt76x2_add_rate_power_offset(&t, -(txp.chain[0].target_power +
txp.chain[0].delta + delta));
dev->target_power = txp.chain[0].target_power;
@@ -325,8 +314,7 @@ mt76x2_configure_tx_delay(struct mt76x2_dev *dev, enum nl80211_band band, u8 bw)
mt76_wr(dev, MT_TX_SW_CFG0, cfg0);
mt76_wr(dev, MT_TX_SW_CFG1, cfg1);
- mt76_rmw_field(dev, MT_XIFS_TIME_CFG, MT_XIFS_TIME_CFG_CCK_SIFS,
- 13 + (bw ? 1 : 0));
+ mt76_rmw_field(dev, MT_XIFS_TIME_CFG, MT_XIFS_TIME_CFG_OFDM_SIFS, 15);
}
static void
@@ -559,7 +547,6 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
u8 bw, bw_index;
int freq, freq1;
int ret;
- u8 sifs = 13;
dev->cal.channel_cal_done = false;
freq = chandef->chan->center_freq;
@@ -611,11 +598,6 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
MT_EXT_CCA_CFG_CCA_MASK),
ext_cca_chan[ch_group_index]);
- if (chandef->width >= NL80211_CHAN_WIDTH_40)
- sifs++;
-
- mt76_rmw_field(dev, MT_XIFS_TIME_CFG, MT_XIFS_TIME_CFG_OFDM_SIFS, sifs);
-
ret = mt76x2_mcu_set_channel(dev, channel, bw, bw_index, scan);
if (ret)
return ret;
@@ -682,7 +664,7 @@ mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev)
return;
dev->cal.tssi_comp_pending = false;
- mt76x2_get_power_info(dev, &txp);
+ mt76x2_get_power_info(dev, &txp, chan);
if (mt76x2_ext_pa_enabled(dev, chan->band))
t.pa_mode = 1;