Commit 1899405c authored by Kalle Valo's avatar Kalle Valo

Merge tag 'mt76-for-kvalo-2019-01-22' of https://github.com/nbd168/wireless

first batch of mt76 patches for 5.1

* fixes for mt76x0/mt76x2
* energy detect regulatory compliance fixes
* tx status handling fixes
* preparation for MT7603 support
* channel switch announcement support
parents 64e23305 d225581d
......@@ -300,7 +300,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
if (q->queued + (n + 1) / 2 >= q->ndesc - 1)
goto unmap;
return dev->queue_ops->add_buf(dev, q, buf, n, tx_info, skb, t);
return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t);
unmap:
ret = -ENOMEM;
......@@ -318,7 +318,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
EXPORT_SYMBOL_GPL(mt76_dma_tx_queue_skb);
static int
mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, bool napi)
mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
{
dma_addr_t addr;
void *buf;
......@@ -392,7 +392,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
mt76_dma_rx_cleanup(dev, q);
mt76_dma_sync_idx(dev, q);
mt76_dma_rx_fill(dev, q, false);
mt76_dma_rx_fill(dev, q);
}
static void
......@@ -417,10 +417,9 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
static int
mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
{
int len, data_len, done = 0;
struct sk_buff *skb;
unsigned char *data;
int len;
int done = 0;
bool more;
while (done < budget) {
......@@ -430,6 +429,19 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
if (!data)
break;
if (q->rx_head)
data_len = q->buf_size;
else
data_len = SKB_WITH_OVERHEAD(q->buf_size);
if (data_len < len + q->buf_offset) {
dev_kfree_skb(q->rx_head);
q->rx_head = NULL;
skb_free_frag(data);
continue;
}
if (q->rx_head) {
mt76_add_fragment(dev, q, data, len, more);
continue;
......@@ -440,12 +452,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
skb_free_frag(data);
continue;
}
skb_reserve(skb, q->buf_offset);
if (skb->tail + len > skb->end) {
dev_kfree_skb(skb);
continue;
}
if (q == &dev->q_rx[MT_RXQ_MCU]) {
u32 *rxfce = (u32 *) skb->cb;
......@@ -463,7 +470,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
dev->drv->rx_skb(dev, q - dev->q_rx, skb);
}
mt76_dma_rx_fill(dev, q, true);
mt76_dma_rx_fill(dev, q);
return done;
}
......@@ -504,7 +511,7 @@ mt76_dma_init(struct mt76_dev *dev)
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
64);
mt76_dma_rx_fill(dev, &dev->q_rx[i], false);
mt76_dma_rx_fill(dev, &dev->q_rx[i]);
skb_queue_head_init(&dev->rx_skb[i]);
napi_enable(&dev->napi[i]);
}
......
......@@ -328,6 +328,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, AP_LINK_PS);
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
......@@ -547,7 +548,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
}
static void
mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
......@@ -566,6 +567,11 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
sta = container_of((void *) wcid, struct ieee80211_sta, drv_priv);
if (status->signal <= 0)
ewma_signal_add(&wcid->rssi, -status->signal);
wcid->inactive_count = 0;
if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
return;
......@@ -625,7 +631,7 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
__skb_queue_head_init(&frames);
while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) {
mt76_check_ps(dev, skb);
mt76_check_sta(dev, skb);
mt76_rx_aggr_reorder(skb, &frames);
}
......@@ -659,6 +665,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
mt76_txq_init(dev, sta->txq[i]);
}
ewma_signal_init(&wcid->rssi);
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
out:
......@@ -709,3 +716,60 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return 0;
}
EXPORT_SYMBOL_GPL(mt76_sta_state);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int *dbm)
{
struct mt76_dev *dev = hw->priv;
int n_chains = __sw_hweight8(dev->antenna_mask);
*dbm = dev->txpower_cur / 2;
/* convert from per-chain power to combined
* output on 2x2 devices
*/
if (n_chains > 1)
*dbm += 3;
return 0;
}
EXPORT_SYMBOL_GPL(mt76_get_txpower);
static void
__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
if (vif->csa_active && ieee80211_csa_is_complete(vif))
ieee80211_csa_finish(vif);
}
void mt76_csa_finish(struct mt76_dev *dev)
{
if (!dev->csa_complete)
return;
ieee80211_iterate_active_interfaces_atomic(dev->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
__mt76_csa_finish, dev);
dev->csa_complete = 0;
}
EXPORT_SYMBOL_GPL(mt76_csa_finish);
static void
__mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt76_dev *dev = priv;
if (!vif->csa_active)
return;
dev->csa_complete |= ieee80211_csa_is_complete(vif);
}
void mt76_csa_check(struct mt76_dev *dev)
{
ieee80211_iterate_active_interfaces_atomic(dev->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
__mt76_csa_check, dev);
}
EXPORT_SYMBOL_GPL(mt76_csa_check);
......@@ -23,6 +23,7 @@
#include <linux/skbuff.h>
#include <linux/leds.h>
#include <linux/usb.h>
#include <linux/average.h>
#include <net/mac80211.h>
#include "util.h"
......@@ -174,6 +175,8 @@ enum mt76_wcid_flags {
#define MT76_N_WCIDS 128
DECLARE_EWMA(signal, 10, 8);
struct mt76_wcid {
struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS];
......@@ -181,6 +184,9 @@ struct mt76_wcid {
unsigned long flags;
struct ewma_signal rssi;
int inactive_count;
u8 idx;
u8 hw_key_idx;
......@@ -239,7 +245,9 @@ struct mt76_rx_tid {
#define MT_TX_CB_TXS_FAILED BIT(2)
#define MT_PACKET_ID_MASK GENMASK(7, 0)
#define MT_PACKET_ID_NO_ACK MT_PACKET_ID_MASK
#define MT_PACKET_ID_NO_ACK 0
#define MT_PACKET_ID_NO_SKB 1
#define MT_PACKET_ID_FIRST 2
#define MT_TX_STATUS_SKB_TIMEOUT HZ
......@@ -421,6 +429,7 @@ struct mt76_dev {
struct mt76_queue q_tx[__MT_TXQ_MAX];
struct mt76_queue q_rx[__MT_RXQ_MAX];
const struct mt76_queue_ops *queue_ops;
int tx_dma_idx[4];
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
......@@ -454,6 +463,8 @@ struct mt76_dev {
bool led_al;
u8 led_pin;
u8 csa_complete;
u32 rxfilter;
union {
......@@ -488,7 +499,7 @@ struct mt76_rx_status {
u8 rate_idx;
u8 nss;
u8 band;
u8 signal;
s8 signal;
u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS];
};
......@@ -677,6 +688,14 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
int mt76_get_min_avg_rssi(struct mt76_dev *dev);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int *dbm);
void mt76_csa_check(struct mt76_dev *dev);
void mt76_csa_finish(struct mt76_dev *dev);
/* internal */
void mt76_tx_free(struct mt76_dev *dev);
struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
......
......@@ -88,6 +88,7 @@ static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
{ MT_TX_PROT_CFG6, 0xe3f42004 },
{ MT_TX_PROT_CFG7, 0xe3f42084 },
{ MT_TX_PROT_CFG8, 0xe3f42104 },
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
};
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
......
......@@ -99,7 +99,7 @@ static const struct ieee80211_ops mt76x0e_ops = {
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.wake_tx_queue = mt76_wake_tx_queue,
.get_survey = mt76_get_survey,
.get_txpower = mt76x02_get_txpower,
.get_txpower = mt76_get_txpower,
.flush = mt76x0e_flush,
.set_tim = mt76x0e_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
......@@ -141,6 +141,15 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
mt76_clear(dev, 0x110, BIT(9));
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
mt76_wr(dev, MT_CH_TIME_CFG,
MT_CH_TIME_CFG_TIMER_EN |
MT_CH_TIME_CFG_TX_AS_BUSY |
MT_CH_TIME_CFG_RX_AS_BUSY |
MT_CH_TIME_CFG_NAV_AS_BUSY |
MT_CH_TIME_CFG_EIFS_AS_BUSY |
MT_CH_CCA_RC_EN |
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
err = mt76x0_register_device(dev);
if (err < 0)
return err;
......
......@@ -1013,6 +1013,8 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
mt76x0_phy_calibrate(dev, false);
mt76x0_phy_set_txpower(dev);
mt76x02_edcca_init(dev);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
......@@ -1075,7 +1077,9 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev)
u8 gain_delta;
int low_gain;
dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76);
if (!dev->cal.avg_rssi_all)
dev->cal.avg_rssi_all = -75;
low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
......
......@@ -155,7 +155,7 @@ static const struct ieee80211_ops mt76x0u_ops = {
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.set_rts_threshold = mt76x02_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
.get_txpower = mt76x02_get_txpower,
.get_txpower = mt76_get_txpower,
};
static int mt76x0u_register_device(struct mt76x02_dev *dev)
......
......@@ -15,6 +15,7 @@
*/
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include "mt76x0.h"
#include "mcu.h"
......
......@@ -15,8 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __MT76X02_UTIL_H
#define __MT76X02_UTIL_H
#ifndef __MT76x02_H
#define __MT76x02_H
#include <linux/kfifo.h>
......@@ -28,6 +28,9 @@
#define MT_CALIBRATE_INTERVAL HZ
#define MT_WATCHDOG_TIME (HZ / 10)
#define MT_TX_HANG_TH 10
#define MT_MAX_CHAINS 2
struct mt76x02_rx_freq_cal {
s8 high_gain[MT_MAX_CHAINS];
......@@ -79,6 +82,7 @@ struct mt76x02_dev {
struct tasklet_struct pre_tbtt_tasklet;
struct delayed_work cal_work;
struct delayed_work mac_work;
struct delayed_work wdt_work;
u32 aggr_stats[32];
......@@ -89,6 +93,9 @@ struct mt76x02_dev {
u8 tbtt_count;
u16 beacon_int;
u32 tx_hang_reset;
u8 tx_hang_check;
struct mt76x02_calibration cal;
s8 target_power;
......@@ -101,6 +108,12 @@ struct mt76x02_dev {
u8 slottime;
struct mt76x02_dfs_pattern_detector dfs_pd;
/* edcca monitor */
bool ed_tx_blocked;
bool ed_monitor;
u8 ed_trigger;
u8 ed_silent;
};
extern struct ieee80211_rate mt76x02_rates[12];
......@@ -136,6 +149,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev,
const struct ieee80211_tx_rate *rate);
s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr,
s8 max_txpwr_adj);
void mt76x02_wdt_work(struct work_struct *work);
void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr);
void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
......@@ -158,8 +172,6 @@ void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac);
void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int mt76x02_get_txpower(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int *dbm);
void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
......@@ -224,4 +236,4 @@ mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast)
return &sta->vif->group_wcid;
}
#endif
#endif /* __MT76x02_H */
......@@ -133,5 +133,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev)
read_txpower);
debugfs_create_devm_seqfile(dev->mt76.dev, "agc", dir, read_agc);
debugfs_create_u32("tx_hang_reset", 0400, dir, &dev->tx_hang_reset);
}
EXPORT_SYMBOL_GPL(mt76x02_init_debugfs);
......@@ -881,12 +881,18 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev,
{
struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
mutex_lock(&dev->mt76.mutex);
if (dfs_pd->region != region) {
tasklet_disable(&dfs_pd->dfs_tasklet);
dev->ed_monitor = region == NL80211_DFS_ETSI;
mt76x02_edcca_init(dev);
dfs_pd->region = region;
mt76x02_dfs_init_params(dev);
tasklet_enable(&dfs_pd->dfs_tasklet);
}
mutex_unlock(&dev->mt76.mutex);
}
void mt76x02_regd_notifier(struct wiphy *wiphy,
......
......@@ -130,10 +130,8 @@ static __le16
mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
const struct ieee80211_tx_rate *rate, u8 *nss_val)
{
u8 phy, rate_idx, nss, bw = 0;
u16 rateval;
u8 phy, rate_idx;
u8 nss = 1;
u8 bw = 0;
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
rate_idx = rate->idx;
......@@ -164,7 +162,7 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
phy = val >> 8;
rate_idx = val & 0xff;
bw = 0;
nss = 1;
}
rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx);
......@@ -435,7 +433,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
}
if (wcid) {
if (stat->pktid)
if (stat->pktid >= MT_PACKET_ID_FIRST)
status.skb = mt76_tx_status_skb_get(mdev, wcid,
stat->pktid, &list);
if (status.skb)
......@@ -478,7 +476,9 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
}
static int
mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
mt76x02_mac_process_rate(struct mt76x02_dev *dev,
struct mt76_rx_status *status,
u16 rate)
{
u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
......@@ -510,11 +510,15 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
status->encoding = RX_ENC_HT;
status->rate_idx = idx;
break;
case MT_PHY_TYPE_VHT:
case MT_PHY_TYPE_VHT: {
u8 n_rxstream = dev->mt76.chainmask & 0xf;
status->encoding = RX_ENC_VHT;
status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx);
status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1;
status->nss = min_t(u8, n_rxstream,
FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1);
break;
}
default:
return -EINVAL;
}
......@@ -644,7 +648,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->chains = BIT(0);
signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0);
for (i = 1; i < nstreams; i++) {
for (i = 0; i < nstreams; i++) {
status->chains |= BIT(i);
status->chain_signal[i] = mt76x02_mac_get_rssi(dev,
rxwi->rssi[i],
......@@ -658,12 +662,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
if (sta) {
ewma_signal_add(&sta->rssi, status->signal);
sta->inactive_count = 0;
}
return mt76x02_mac_process_rate(status, rate);
return mt76x02_mac_process_rate(dev, status, rate);
}
void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq)
......@@ -715,7 +714,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
}
EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val)
{
u32 data = 0;
......@@ -729,20 +728,89 @@ void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_OFDM_PROT_CFG,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_MM20_PROT_CFG,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_MM40_PROT_CFG,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_GF20_PROT_CFG,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_GF40_PROT_CFG,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_TX_PROT_CFG6,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_TX_PROT_CFG7,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_TX_PROT_CFG8,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
}
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
int ht_mode)
{
int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
u32 prot[6];
u32 vht_prot[3];
int i;
u16 rts_thr;
for (i = 0; i < ARRAY_SIZE(prot); i++) {
prot[i] = mt76_rr(dev, MT_CCK_PROT_CFG + i * 4);
prot[i] &= ~MT_PROT_CFG_CTRL;
if (i >= 2)
prot[i] &= ~MT_PROT_CFG_RATE;
}
for (i = 0; i < ARRAY_SIZE(vht_prot); i++) {
vht_prot[i] = mt76_rr(dev, MT_TX_PROT_CFG6 + i * 4);
vht_prot[i] &= ~(MT_PROT_CFG_CTRL | MT_PROT_CFG_RATE);
}
rts_thr = mt76_get_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH);
if (rts_thr != 0xffff)
prot[0] |= MT_PROT_CTRL_RTS_CTS;
if (legacy_prot) {
prot[1] |= MT_PROT_CTRL_CTS2SELF;
prot[2] |= MT_PROT_RATE_CCK_11;
prot[3] |= MT_PROT_RATE_CCK_11;
prot[4] |= MT_PROT_RATE_CCK_11;
prot[5] |= MT_PROT_RATE_CCK_11;
vht_prot[0] |= MT_PROT_RATE_CCK_11;
vht_prot[1] |= MT_PROT_RATE_CCK_11;
vht_prot[2] |= MT_PROT_RATE_CCK_11;
} else {
if (rts_thr != 0xffff)
prot[1] |= MT_PROT_CTRL_RTS_CTS;
prot[2] |= MT_PROT_RATE_OFDM_24;
prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
prot[4] |= MT_PROT_RATE_OFDM_24;
prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
vht_prot[0] |= MT_PROT_RATE_OFDM_24;
vht_prot[1] |= MT_PROT_RATE_DUP_OFDM_24;
vht_prot[2] |= MT_PROT_RATE_SGI_OFDM_24;
}
switch (mode) {
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
prot[2] |= MT_PROT_CTRL_RTS_CTS;
prot[3] |= MT_PROT_CTRL_RTS_CTS;
prot[4] |= MT_PROT_CTRL_RTS_CTS;
prot[5] |= MT_PROT_CTRL_RTS_CTS;
vht_prot[0] |= MT_PROT_CTRL_RTS_CTS;
vht_prot[1] |= MT_PROT_CTRL_RTS_CTS;
vht_prot[2] |= MT_PROT_CTRL_RTS_CTS;
break;
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
prot[3] |= MT_PROT_CTRL_RTS_CTS;
prot[5] |= MT_PROT_CTRL_RTS_CTS;
vht_prot[1] |= MT_PROT_CTRL_RTS_CTS;
vht_prot[2] |= MT_PROT_CTRL_RTS_CTS;
break;
}
if (non_gf) {
prot[4] |= MT_PROT_CTRL_RTS_CTS;
prot[5] |= MT_PROT_CTRL_RTS_CTS;
}
for (i = 0; i < ARRAY_SIZE(prot); i++)
mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
for (i = 0; i < ARRAY_SIZE(vht_prot); i++)
mt76_wr(dev, MT_TX_PROT_CFG6 + i * 4, vht_prot[i]);
}
void mt76x02_update_channel(struct mt76_dev *mdev)
......@@ -774,16 +842,100 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
udelay(10);
mt76_clear(dev, MT_MAC_SYS_CTRL,
mt76_wr(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
}
static void
mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable)
{
if (enable) {
u32 data;
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN);
/* enable pa-lna */
data = mt76_rr(dev, MT_TX_PIN_CFG);
data |= MT_TX_PIN_CFG_TXANT |
MT_TX_PIN_CFG_RXANT |
MT_TX_PIN_RFTR_EN |
MT_TX_PIN_TRSW_EN;
mt76_wr(dev, MT_TX_PIN_CFG, data);
} else {
mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN);
/* disable pa-lna */
mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT);
mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_RXANT);
}
dev->ed_tx_blocked = !enable;
}
void mt76x02_edcca_init(struct mt76x02_dev *dev)
{
dev->ed_trigger = 0;
dev->ed_silent = 0;
if (dev->ed_monitor) {
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20;
mt76_clear(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN);
mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0),
ed_th << 8 | ed_th);
if (!is_mt76x2(dev))
mt76_set(dev, MT_TXOP_HLDR_ET,
MT_TXOP_HLDR_TX40M_BLK_EN);
} else {
mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN);
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
if (is_mt76x2(dev)) {
mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070);
} else {
mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464);
mt76_clear(dev, MT_TXOP_HLDR_ET,
MT_TXOP_HLDR_TX40M_BLK_EN);
}
}
mt76x02_edcca_tx_enable(dev, true);
}
EXPORT_SYMBOL_GPL(mt76x02_edcca_init);
#define MT_EDCCA_TH 90
#define MT_EDCCA_BLOCK_TH 2
static void mt76x02_edcca_check(struct mt76x02_dev *dev)
{
u32 val, busy;
val = mt76_rr(dev, MT_ED_CCA_TIMER);
busy = (val * 100) / jiffies_to_usecs(MT_CALIBRATE_INTERVAL);
busy = min_t(u32, busy, 100);
if (busy > MT_EDCCA_TH) {
dev->ed_trigger++;
dev->ed_silent = 0;
} else {
dev->ed_silent++;
dev->ed_trigger = 0;
}
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)
mt76x02_edcca_tx_enable(dev, true);
}
void mt76x02_mac_work(struct work_struct *work)
{
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
mac_work.work);
int i, idx;
mutex_lock(&dev->mt76.mutex);
mt76x02_update_channel(&dev->mt76);
for (i = 0, idx = 0; i < 16; i++) {
u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i));
......@@ -792,10 +944,14 @@ void mt76x02_mac_work(struct work_struct *work)
dev->aggr_stats[idx++] += val >> 16;
}
/* XXX: check beacon stuck for ap mode */
if (!dev->beacon_mask)
mt76x02_check_mac_err(dev);
if (dev->ed_monitor)
mt76x02_edcca_check(dev);
mutex_unlock(&dev->mt76.mutex);
mt76_tx_status_check(&dev->mt76, NULL, false);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
......
......@@ -18,8 +18,6 @@
#ifndef __MT76X02_MAC_H
#define __MT76X02_MAC_H
#include <linux/average.h>
struct mt76x02_dev;
struct mt76x02_tx_status {
......@@ -41,8 +39,6 @@ struct mt76x02_vif {
u8 idx;
};
DECLARE_EWMA(signal, 10, 8);
struct mt76x02_sta {
struct mt76_wcid wcid; /* must be first */
......@@ -50,8 +46,6 @@ struct mt76x02_sta {
struct mt76x02_tx_status status;
int n_frames;
struct ewma_signal rssi;
int inactive_count;
};
#define MT_RXINFO_BA BIT(0)
......@@ -194,7 +188,9 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
struct mt76x02_tx_status *stat, u8 *update);
int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
void *rxi);
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val);
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
int ht_mode);
void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val);
void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr);
void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
......@@ -210,4 +206,6 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
struct sk_buff *skb);
void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
bool val);
void mt76x02_edcca_init(struct mt76x02_dev *dev);
#endif
......@@ -116,14 +116,20 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_update_beacon_iter, dev);
mt76_csa_check(&dev->mt76);
if (dev->mt76.csa_complete)
return;
do {
nframes = skb_queue_len(&data.q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_add_buffered_bc, &data);
} while (nframes != skb_queue_len(&data.q));
} while (nframes != skb_queue_len(&data.q) &&
skb_queue_len(&data.q) < 8);
if (!nframes)
if (!skb_queue_len(&data.q))
return;
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
......@@ -308,8 +314,12 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
tasklet_schedule(&dev->pre_tbtt_tasklet);
/* send buffered multicast frames now */
if (intr & MT_INT_TBTT)
if (intr & MT_INT_TBTT) {
if (dev->mt76.csa_complete)
mt76_csa_finish(&dev->mt76);
else
mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
}
if (intr & MT_INT_TX_STAT) {
mt76x02_mac_poll_tx_status(dev, true);
......@@ -384,3 +394,127 @@ void mt76x02_mac_start(struct mt76x02_dev *dev)
MT_INT_TX_STAT);
}
EXPORT_SYMBOL_GPL(mt76x02_mac_start);
static bool mt76x02_tx_hang(struct mt76x02_dev *dev)
{
u32 dma_idx, prev_dma_idx;
struct mt76_queue *q;
int i;
for (i = 0; i < 4; i++) {
q = &dev->mt76.q_tx[i];
if (!q->queued)
continue;
prev_dma_idx = dev->mt76.tx_dma_idx[i];
dma_idx = ioread32(&q->regs->dma_idx);
dev->mt76.tx_dma_idx[i] = dma_idx;
if (prev_dma_idx == dma_idx)
break;
}
return i < 4;
}
static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
{
u32 mask = dev->mt76.mmio.irqmask;
int i;
ieee80211_stop_queues(dev->mt76.hw);
set_bit(MT76_RESET, &dev->mt76.state);
tasklet_disable(&dev->pre_tbtt_tasklet);
tasklet_disable(&dev->tx_tasklet);
for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++)
napi_disable(&dev->mt76.napi[i]);
mutex_lock(&dev->mt76.mutex);
if (dev->beacon_mask)
mt76_clear(dev, MT_BEACON_TIME_CFG,
MT_BEACON_TIME_CFG_BEACON_TX |
MT_BEACON_TIME_CFG_TBTT_EN);
mt76x02_irq_disable(dev, mask);
/* perform device reset */
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
mt76_clear(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN);
usleep_range(5000, 10000);
mt76_wr(dev, MT_INT_SOURCE_CSR, 0xffffffff);
/* let fw reset DMA */
mt76_set(dev, 0x734, 0x3);
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);
if (dev->ed_monitor)
mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
if (dev->beacon_mask)
mt76_set(dev, MT_BEACON_TIME_CFG,
MT_BEACON_TIME_CFG_BEACON_TX |
MT_BEACON_TIME_CFG_TBTT_EN);
mt76x02_irq_enable(dev, mask);
mutex_unlock(&dev->mt76.mutex);
clear_bit(MT76_RESET, &dev->mt76.state);
tasklet_enable(&dev->tx_tasklet);
tasklet_schedule(&dev->tx_tasklet);
tasklet_enable(&dev->pre_tbtt_tasklet);
for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
ieee80211_wake_queues(dev->mt76.hw);
mt76_txq_schedule_all(&dev->mt76);
}
static void mt76x02_check_tx_hang(struct mt76x02_dev *dev)
{
if (mt76x02_tx_hang(dev)) {
if (++dev->tx_hang_check < MT_TX_HANG_TH)
return;
mt76x02_watchdog_reset(dev);
dev->tx_hang_reset++;
dev->tx_hang_check = 0;
memset(dev->mt76.tx_dma_idx, 0xff,
sizeof(dev->mt76.tx_dma_idx));
} else {
dev->tx_hang_check = 0;
}
}
void mt76x02_wdt_work(struct work_struct *work)
{
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
wdt_work.work);
mt76x02_check_tx_hang(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
MT_WATCHDOG_TIME);
}
......@@ -132,53 +132,6 @@ void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1)
}
EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower);
int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev)
{
struct mt76x02_sta *sta;
struct mt76_wcid *wcid;
int i, j, min_rssi = 0;
s8 cur_rssi;
local_bh_disable();
rcu_read_lock();
for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) {
unsigned long mask = dev->mt76.wcid_mask[i];
if (!mask)
continue;
for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
if (!(mask & 1))
continue;
wcid = rcu_dereference(dev->mt76.wcid[j]);
if (!wcid)
continue;
sta = container_of(wcid, struct mt76x02_sta, wcid);
spin_lock(&dev->mt76.rx_lock);
if (sta->inactive_count++ < 5)
cur_rssi = ewma_signal_read(&sta->rssi);
else
cur_rssi = 0;
spin_unlock(&dev->mt76.rx_lock);
if (cur_rssi < min_rssi)
min_rssi = cur_rssi;
}
}
rcu_read_unlock();
local_bh_enable();
if (!min_rssi)
return -75;
return min_rssi;
}
EXPORT_SYMBOL_GPL(mt76x02_phy_get_min_avg_rssi);
void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl)
{
int core_val, agc_val;
......
......@@ -51,7 +51,6 @@ void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit);
int mt76x02_get_max_rate_power(struct mt76_rate_power *r);
void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev);
void mt76x02_phy_set_txdac(struct mt76x02_dev *dev);
int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev);
void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl);
void mt76x02_phy_set_band(struct mt76x02_dev *dev, int band,
bool primary_upper);
......
......@@ -230,6 +230,29 @@
#define MT_COM_REG2 0x0738
#define MT_COM_REG3 0x073C
#define MT_LED_CTRL 0x0770
#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
#define MT_LED_TX_BLINK_0 0x0774
#define MT_LED_TX_BLINK_1 0x0778
#define MT_LED_S0_BASE 0x077C
#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n))
#define MT_LED_S1_BASE 0x0780
#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n))
#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \
MT_LED_STATUS_OFF_MASK)
#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \
MT_LED_STATUS_ON_MASK)
#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8)
#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
MT_LED_STATUS_DURATION_MASK)
#define MT_FCE_PSE_CTRL 0x0800
#define MT_FCE_PARAMETERS 0x0804
#define MT_FCE_CSO 0x0808
......@@ -318,6 +341,7 @@
#define MT_CH_TIME_CFG_NAV_AS_BUSY BIT(3)
#define MT_CH_TIME_CFG_EIFS_AS_BUSY BIT(4)
#define MT_CH_TIME_CFG_MDRDY_CNT_EN BIT(5)
#define MT_CH_CCA_RC_EN BIT(6)
#define MT_CH_TIME_CFG_CH_TIMER_CLR GENMASK(9, 8)
#define MT_CH_TIME_CFG_MDRDY_CLR GENMASK(11, 10)
......@@ -378,6 +402,9 @@
#define MT_TX_PWR_CFG_4 0x1324
#define MT_TX_PIN_CFG 0x1328
#define MT_TX_PIN_CFG_TXANT GENMASK(3, 0)
#define MT_TX_PIN_CFG_RXANT GENMASK(11, 8)
#define MT_TX_PIN_RFTR_EN BIT(16)
#define MT_TX_PIN_TRSW_EN BIT(18)
#define MT_TX_BAND_CFG 0x132c
#define MT_TX_BAND_CFG_UPPER_40M BIT(0)
......@@ -398,6 +425,7 @@
#define MT_TXOP_CTRL_CFG 0x1340
#define MT_TXOP_TRUN_EN GENMASK(5, 0)
#define MT_TXOP_EXT_CCA_DLY GENMASK(15, 8)
#define MT_TXOP_ED_CCA_EN BIT(20)
#define MT_TX_RTS_CFG 0x1344
#define MT_TX_RTS_CFG_RETRY_LIMIT GENMASK(7, 0)
......@@ -409,6 +437,7 @@
#define MT_TX_RETRY_CFG 0x134c
#define MT_TX_LINK_CFG 0x1350
#define MT_TX_CFACK_EN BIT(12)
#define MT_VHT_HT_FBK_CFG0 0x1354
#define MT_VHT_HT_FBK_CFG1 0x1358
#define MT_LG_FBK_CFG0 0x135c
......@@ -440,9 +469,10 @@
#define MT_PROT_TXOP_ALLOW_GF40 BIT(25)
#define MT_PROT_RTS_THR_EN BIT(26)
#define MT_PROT_RATE_CCK_11 0x0003
#define MT_PROT_RATE_OFDM_6 0x4000
#define MT_PROT_RATE_OFDM_24 0x4004
#define MT_PROT_RATE_DUP_OFDM_24 0x4084
#define MT_PROT_RATE_OFDM_6 0x2000
#define MT_PROT_RATE_OFDM_24 0x2004
#define MT_PROT_RATE_DUP_OFDM_24 0x2084
#define MT_PROT_RATE_SGI_OFDM_24 0x2104
#define MT_PROT_TXOP_ALLOW_ALL GENMASK(25, 20)
#define MT_PROT_TXOP_ALLOW_BW20 (MT_PROT_TXOP_ALLOW_ALL & \
~MT_PROT_TXOP_ALLOW_MM40 & \
......@@ -511,6 +541,7 @@
#define MT_RX_FILTR_CFG_CTRL_RSV BIT(16)
#define MT_AUTO_RSP_CFG 0x1404
#define MT_AUTO_RSP_EN BIT(0)
#define MT_AUTO_RSP_PREAMB_SHORT BIT(4)
#define MT_LEGACY_BASIC_RATE 0x1408
#define MT_HT_BASIC_RATE 0x140c
......@@ -532,6 +563,7 @@
#define MT_PN_PAD_MODE 0x150c
#define MT_TXOP_HLDR_ET 0x1608
#define MT_TXOP_HLDR_TX40M_BLK_EN BIT(1)
#define MT_PROT_AUTO_TX_CFG 0x1648
#define MT_PROT_AUTO_TX_CFG_PROT_PADJ GENMASK(11, 8)
......
......@@ -177,7 +177,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (ret < 0)
return ret;
if (pid && pid != MT_PACKET_ID_NO_ACK)
if (pid >= MT_PACKET_ID_FIRST)
qsel = MT_QSEL_MGMT;
*tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
......
......@@ -87,8 +87,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
pid = mt76_tx_status_skb_add(mdev, wcid, skb);
txwi->pktid = pid;
if ((pid && pid != MT_PACKET_ID_NO_ACK) ||
q2ep(q->hw_idx) == MT_EP_OUT_HCCA)
if (pid >= MT_PACKET_ID_FIRST || q2ep(q->hw_idx) == MT_EP_OUT_HCCA)
qsel = MT_QSEL_MGMT;
else
qsel = MT_QSEL_EDCA;
......
......@@ -75,6 +75,58 @@ static const struct ieee80211_iface_combination mt76x02_if_comb[] = {
}
};
static void
mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on,
u8 delay_off)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev,
mt76);
u32 val;
val = MT_LED_STATUS_DURATION(0xff) |
MT_LED_STATUS_OFF(delay_off) |
MT_LED_STATUS_ON(delay_on);
mt76_wr(dev, MT_LED_S0(mdev->led_pin), val);
mt76_wr(dev, MT_LED_S1(mdev->led_pin), val);
val = MT_LED_CTRL_REPLAY(mdev->led_pin) |
MT_LED_CTRL_KICK(mdev->led_pin);
if (mdev->led_al)
val |= MT_LED_CTRL_POLARITY(mdev->led_pin);
mt76_wr(dev, MT_LED_CTRL, val);
}
static int
mt76x02_led_set_blink(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev,
led_cdev);
u8 delta_on, delta_off;
delta_off = max_t(u8, *delay_off / 10, 1);
delta_on = max_t(u8, *delay_on / 10, 1);
mt76x02_led_set_config(mdev, delta_on, delta_off);
return 0;
}
static void
mt76x02_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev,
led_cdev);
if (!brightness)
mt76x02_led_set_config(mdev, 0, 0xff);
else
mt76x02_led_set_config(mdev, 0xff, 0);
}
void mt76x02_init_device(struct mt76x02_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
......@@ -93,6 +145,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
MT_DMA_HDR_LEN;
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
} else {
INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work);
mt76x02_dfs_init_detector(dev);
wiphy->reg_notifier = mt76x02_regd_notifier;
......@@ -106,7 +160,16 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
#endif
BIT(NL80211_IFTYPE_ADHOC);
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
dev->mt76.led_cdev.brightness_set =
mt76x02_led_set_brightness;
dev->mt76.led_cdev.blink_set = mt76x02_led_set_blink;
}
}
hw->sta_data_size = sizeof(struct mt76x02_sta);
......@@ -189,8 +252,6 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_AP)
set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);
ewma_signal_init(&msta->rssi);
return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_sta_add);
......@@ -463,7 +524,7 @@ int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
return -EINVAL;
mutex_lock(&dev->mt76.mutex);
mt76x02_mac_set_tx_protection(dev, val);
mt76x02_mac_set_rts_thresh(dev, val);
mutex_unlock(&dev->mt76.mutex);
return 0;
......@@ -546,24 +607,6 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(mt76x02_sw_scan_complete);
int mt76x02_get_txpower(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int *dbm)
{
struct mt76x02_dev *dev = hw->priv;
u8 nstreams = dev->mt76.chainmask & 0xf;
*dbm = dev->mt76.txpower_cur / 2;
/* convert from per-chain power to combined
* output on 2x2 devices
*/
if (nstreams > 1)
*dbm += 3;
return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_get_txpower);
void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta,
bool ps)
{
......@@ -661,6 +704,10 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
tasklet_enable(&dev->pre_tbtt_tasklet);
}
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
mt76x02_mac_set_tx_protection(dev, info->use_cts_prot,
info->ht_operation_mode);
if (changed & BSS_CHANGED_BEACON_INT) {
mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
MT_BEACON_TIME_CFG_INTVAL,
......
......@@ -143,6 +143,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev)
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
{ MT_PROT_AUTO_TX_CFG, 0x00830083 },
{ MT_HT_CTRL_CFG, 0x000001ff },
{ MT_TX_LINK_CFG, 0x00001020 },
};
struct mt76_reg_pair prot_vals[] = {
{ MT_CCK_PROT_CFG, DEFAULT_PROT_CFG_CCK },
......
......@@ -26,29 +26,6 @@
#define MT_MCU_PCIE_REMAP_BASE2 0x0744
#define MT_MCU_PCIE_REMAP_BASE3 0x0748
#define MT_LED_CTRL 0x0770
#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
#define MT_LED_TX_BLINK_0 0x0774
#define MT_LED_TX_BLINK_1 0x0778
#define MT_LED_S0_BASE 0x077C
#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n))
#define MT_LED_S1_BASE 0x0780
#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n))
#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \
MT_LED_STATUS_OFF_MASK)
#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \
MT_LED_STATUS_ON_MASK)
#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8)
#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
MT_LED_STATUS_DURATION_MASK)
#define MT_MCU_ROM_PATCH_OFFSET 0x80000
#define MT_MCU_ROM_PATCH_ADDR 0x90000
......
......@@ -53,7 +53,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev);
int mt76x2_register_device(struct mt76x02_dev *dev);
void mt76x2_phy_power_on(struct mt76x02_dev *dev);
int mt76x2_init_hardware(struct mt76x02_dev *dev);
void mt76x2_stop_hardware(struct mt76x02_dev *dev);
int mt76x2_eeprom_init(struct mt76x02_dev *dev);
int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel);
......
......@@ -151,6 +151,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
MT_CH_TIME_CFG_RX_AS_BUSY |
MT_CH_TIME_CFG_NAV_AS_BUSY |
MT_CH_TIME_CFG_EIFS_AS_BUSY |
MT_CH_CCA_RC_EN |
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
mt76x02_set_tx_ackto(dev);
......@@ -260,7 +261,7 @@ mt76x2_power_on(struct mt76x02_dev *dev)
mt76x2_power_on_rf(dev, 1);
}
int mt76x2_init_hardware(struct mt76x02_dev *dev)
static int mt76x2_init_hardware(struct mt76x02_dev *dev)
{
int ret;
......@@ -300,6 +301,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mac_work);
cancel_delayed_work_sync(&dev->wdt_work);
mt76x02_mcu_set_radio_state(dev, false);
mt76x2_mac_stop(dev, false);
}
......@@ -340,54 +342,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev)
return dev;
}
static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on,
u8 delay_off)
{
struct mt76x02_dev *dev = container_of(mt76, struct mt76x02_dev,
mt76);
u32 val;
val = MT_LED_STATUS_DURATION(0xff) |
MT_LED_STATUS_OFF(delay_off) |
MT_LED_STATUS_ON(delay_on);
mt76_wr(dev, MT_LED_S0(mt76->led_pin), val);
mt76_wr(dev, MT_LED_S1(mt76->led_pin), val);
val = MT_LED_CTRL_REPLAY(mt76->led_pin) |
MT_LED_CTRL_KICK(mt76->led_pin);
if (mt76->led_al)
val |= MT_LED_CTRL_POLARITY(mt76->led_pin);
mt76_wr(dev, MT_LED_CTRL, val);
}
static int mt76x2_led_set_blink(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
led_cdev);
u8 delta_on, delta_off;
delta_off = max_t(u8, *delay_off / 10, 1);
delta_on = max_t(u8, *delay_on / 10, 1);
mt76x2_led_set_config(mt76, delta_on, delta_off);
return 0;
}
static void mt76x2_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
led_cdev);
if (!brightness)
mt76x2_led_set_config(mt76, 0, 0xff);
else
mt76x2_led_set_config(mt76, 0xff, 0);
}
int mt76x2_register_device(struct mt76x02_dev *dev)
{
int ret;
......@@ -402,12 +356,6 @@ int mt76x2_register_device(struct mt76x02_dev *dev)
mt76x02_config_mac_addr_list(dev);
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
}
ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
ARRAY_SIZE(mt76x02_rates));
if (ret)
......
......@@ -34,6 +34,8 @@ mt76x2_start(struct ieee80211_hw *hw)
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
MT_CALIBRATE_INTERVAL);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
MT_WATCHDOG_TIME);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
......@@ -189,7 +191,7 @@ const struct ieee80211_ops mt76x2_ops = {
.sw_scan_complete = mt76x02_sw_scan_complete,
.flush = mt76x2_flush,
.ampdu_action = mt76x02_ampdu_action,
.get_txpower = mt76x02_get_txpower,
.get_txpower = mt76_get_txpower,
.wake_tx_queue = mt76_wake_tx_queue,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.release_buffered_frames = mt76_release_buffered_frames,
......
......@@ -254,6 +254,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
0x38);
}
mt76x02_edcca_init(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work,
MT_CALIBRATE_INTERVAL);
......
......@@ -284,7 +284,9 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
int low_gain;
u32 val;
dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76);
if (!dev->cal.avg_rssi_all)
dev->cal.avg_rssi_all = -75;
low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
......
......@@ -138,5 +138,5 @@ const struct ieee80211_ops mt76x2u_ops = {
.sw_scan_start = mt76x02_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.get_txpower = mt76x02_get_txpower,
.get_txpower = mt76_get_txpower,
};
......@@ -39,7 +39,7 @@ static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev)
static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev)
{
struct mt76_usb *usb = &dev->mt76.usb;
const u8 data[] = {
static const u8 data[] = {
0x6f, 0xfc, 0x08, 0x01,
0x20, 0x04, 0x00, 0x00,
0x00, 0x09, 0x00,
......
......@@ -170,21 +170,22 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
int pid;
if (!wcid)
return 0;
return MT_PACKET_ID_NO_ACK;
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
return MT_PACKET_ID_NO_ACK;
if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_CTL_RATE_CTRL_PROBE)))
return 0;
return MT_PACKET_ID_NO_SKB;
spin_lock_bh(&dev->status_list.lock);
memset(cb, 0, sizeof(*cb));
wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
if (!wcid->packet_id || wcid->packet_id == MT_PACKET_ID_NO_ACK)
wcid->packet_id = 1;
if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
wcid->packet_id == MT_PACKET_ID_NO_SKB)
wcid->packet_id = MT_PACKET_ID_FIRST;
pid = wcid->packet_id;
cb->wcid = wcid->idx;
......@@ -330,7 +331,8 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
if (last)
info->flags |= IEEE80211_TX_STATUS_EOSP;
info->flags |= IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS;
mt76_skb_set_moredata(skb, !last);
dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, sta);
......@@ -394,6 +396,11 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq,
bool probe;
int idx;
if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) {
*empty = true;
return 0;
}
skb = mt76_txq_dequeue(dev, mtxq, false);
if (!skb) {
*empty = true;
......
......@@ -407,17 +407,15 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
if (len < 0)
return 0;
data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size))
return 0;
skb = build_skb(data, q->buf_size);
if (!skb)
return 0;
data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
skb_reserve(skb, MT_DMA_HDR_LEN);
if (skb->tail + data_len > skb->end) {
dev_kfree_skb(skb);
return 1;
}
__skb_put(skb, data_len);
len -= data_len;
......@@ -585,6 +583,7 @@ static void mt76u_stop_rx(struct mt76_dev *dev)
static void mt76u_tx_tasklet(unsigned long data)
{
struct mt76_dev *dev = (struct mt76_dev *)data;
struct mt76_queue_entry entry;
struct mt76u_buf *buf;
struct mt76_queue *q;
bool wake;
......@@ -599,17 +598,18 @@ static void mt76u_tx_tasklet(unsigned long data)
if (!buf->done || !q->queued)
break;
dev->drv->tx_complete_skb(dev, q,
&q->entry[q->head],
false);
if (q->entry[q->head].schedule) {
q->entry[q->head].schedule = false;
q->swq_queued--;
}
entry = q->entry[q->head];
q->head = (q->head + 1) % q->ndesc;
q->queued--;
spin_unlock_bh(&q->lock);
dev->drv->tx_complete_skb(dev, q, &entry, false);
spin_lock_bh(&q->lock);
}
mt76_txq_schedule(dev, q);
wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
......
......@@ -75,4 +75,46 @@ int mt76_wcid_alloc(unsigned long *mask, int size)
}
EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
int mt76_get_min_avg_rssi(struct mt76_dev *dev)
{
struct mt76_wcid *wcid;
int i, j, min_rssi = 0;
s8 cur_rssi;
local_bh_disable();
rcu_read_lock();
for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
unsigned long mask = dev->wcid_mask[i];
if (!mask)
continue;
for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
if (!(mask & 1))
continue;
wcid = rcu_dereference(dev->wcid[j]);
if (!wcid)
continue;
spin_lock(&dev->rx_lock);
if (wcid->inactive_count++ < 5)
cur_rssi = -ewma_signal_read(&wcid->rssi);
else
cur_rssi = 0;
spin_unlock(&dev->rx_lock);
if (cur_rssi < min_rssi)
min_rssi = cur_rssi;
}
}
rcu_read_unlock();
local_bh_enable();
return min_rssi;
}
EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);
MODULE_LICENSE("Dual BSD/GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment