Commit 074b145a authored by Kalle Valo's avatar Kalle Valo

Merge tag 'mt76-for-kvalo-2018-11-30' of https://github.com/nbd168/wireless

first batch of mt76 patches for 4.21

* use the same firmware for mt76x2e and mt76x2u
* mt76x2 fixes
* mt76x0 fixes
* mt76x0e survey support
* more unification between mt76x2 and mt76x0
* mt76x0e AP mode support
* mt76x0e DFS support
* rework and fix tx status handling for mt76x0 and mt76x2

kvalo: fixed a conflict in drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
and a build problem in drivers/net/wireless/mediatek/mt76/mt76x02_util.c
parents d9bbd6a1 e28487ea
......@@ -14,7 +14,8 @@ CFLAGS_mt76x02_trace.o := -I$(src)
mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \
mt76x02_txrx.o mt76x02_trace.o
mt76x02_txrx.o mt76x02_trace.o mt76x02_debugfs.o \
mt76x02_dfs.o
mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
......
......@@ -157,17 +157,20 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
if (entry.schedule)
q->swq_queued--;
if (entry.skb)
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
if (entry.skb) {
spin_unlock_bh(&q->lock);
dev->drv->tx_complete_skb(dev, q, &entry, flush);
spin_lock_bh(&q->lock);
}
if (entry.txwi) {
mt76_put_txwi(dev, entry.txwi);
wake = true;
wake = !flush;
}
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
if (!flush && q->tail == last)
last = ioread32(&q->regs->dma_idx);
}
......@@ -258,6 +261,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
return -ENOMEM;
}
skb->prev = skb->next = NULL;
dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi),
DMA_TO_DEVICE);
ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, q, wcid, sta,
......
......@@ -285,6 +285,7 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops)
spin_lock_init(&dev->cc_lock);
mutex_init(&dev->mutex);
init_waitqueue_head(&dev->tx_wait);
skb_queue_head_init(&dev->status_list);
return dev;
}
......@@ -326,6 +327,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
ieee80211_hw_set(hw, TX_FRAG_LIST);
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, AP_LINK_PS);
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
......@@ -359,6 +361,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
{
struct ieee80211_hw *hw = dev->hw;
mt76_tx_status_check(dev, NULL, true);
ieee80211_unregister_hw(hw);
mt76_tx_free(dev);
}
......@@ -629,3 +632,80 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
mt76_rx_complete(dev, &frames, napi);
}
EXPORT_SYMBOL_GPL(mt76_rx_poll_complete);
static int
mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
int ret;
int i;
mutex_lock(&dev->mutex);
ret = dev->drv->sta_add(dev, vif, sta);
if (ret)
goto out;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct mt76_txq *mtxq;
if (!sta->txq[i])
continue;
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
mtxq->wcid = wcid;
mt76_txq_init(dev, sta->txq[i]);
}
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
out:
mutex_unlock(&dev->mutex);
return ret;
}
static 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;
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);
mt76_tx_status_check(dev, wcid, true);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
mt76_txq_remove(dev, sta->txq[i]);
mt76_wcid_free(dev->wcid_mask, idx);
mutex_unlock(&dev->mutex);
}
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)
{
struct mt76_dev *dev = hw->priv;
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE)
return mt76_sta_add(dev, vif, sta);
if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)
mt76_sta_remove(dev, vif, sta);
return 0;
}
EXPORT_SYMBOL_GPL(mt76_sta_state);
......@@ -135,9 +135,8 @@ struct mt76_queue {
};
struct mt76_mcu_ops {
struct sk_buff *(*mcu_msg_alloc)(const void *data, int len);
int (*mcu_send_msg)(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, bool wait_resp);
int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data,
int len, bool wait_resp);
int (*mcu_wr_rp)(struct mt76_dev *dev, u32 base,
const struct mt76_reg_pair *rp, int len);
int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base,
......@@ -195,6 +194,8 @@ struct mt76_wcid {
u8 tx_rate_nss;
s8 max_txpwr_adj;
bool sw_iv;
u8 packet_id;
};
struct mt76_txq {
......@@ -233,6 +234,22 @@ struct mt76_rx_tid {
struct sk_buff *reorder_buf[];
};
#define MT_TX_CB_DMA_DONE BIT(0)
#define MT_TX_CB_TXS_DONE BIT(1)
#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_TX_STATUS_SKB_TIMEOUT HZ
struct mt76_tx_cb {
unsigned long jiffies;
u8 wcid;
u8 pktid;
u8 flags;
};
enum {
MT76_STATE_INITIALIZED,
MT76_STATE_RUNNING,
......@@ -271,6 +288,12 @@ struct mt76_driver_ops {
void (*sta_ps)(struct mt76_dev *dev, struct ieee80211_sta *sta,
bool ps);
int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
};
struct mt76_channel_state {
......@@ -400,6 +423,7 @@ struct mt76_dev {
const struct mt76_queue_ops *queue_ops;
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG];
......@@ -484,7 +508,6 @@ struct mt76_rx_status {
#define mt76_wr_rp(dev, ...) (dev)->mt76.bus->wr_rp(&((dev)->mt76), __VA_ARGS__)
#define mt76_rd_rp(dev, ...) (dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__)
#define mt76_mcu_msg_alloc(dev, ...) (dev)->mt76.mcu_ops->mcu_msg_alloc(__VA_ARGS__)
#define mt76_mcu_send_msg(dev, ...) (dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__)
#define mt76_set(dev, offset, val) mt76_rmw(dev, offset, 0, val)
......@@ -594,6 +617,13 @@ wcid_to_sta(struct mt76_wcid *wcid)
return container_of(ptr, struct ieee80211_sta, drv_priv);
}
static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct mt76_tx_cb) >
sizeof(IEEE80211_SKB_CB(skb)->status.status_driver_data));
return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data);
}
int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta);
......@@ -625,6 +655,26 @@ void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid);
void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key);
void mt76_tx_status_lock(struct mt76_dev *dev, struct sk_buff_head *list)
__acquires(&dev->status_list.lock);
void mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
__releases(&dev->status_list.lock);
int mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct sk_buff *skb);
struct sk_buff *mt76_tx_status_skb_get(struct mt76_dev *dev,
struct mt76_wcid *wcid, int pktid,
struct sk_buff_head *list);
void mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb,
struct sk_buff_head *list);
void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb);
void mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid,
bool flush);
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);
struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
/* internal */
......@@ -668,8 +718,6 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
void *buf, size_t len);
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
const u16 offset, const u32 val);
u32 mt76u_rr(struct mt76_dev *dev, u32 addr);
void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val);
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
void mt76u_deinit(struct mt76_dev *dev);
int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
......
......@@ -2,11 +2,9 @@ obj-$(CONFIG_MT76x0U) += mt76x0u.o
obj-$(CONFIG_MT76x0E) += mt76x0e.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o
mt76x0-common-y := \
init.o main.o trace.o eeprom.o phy.o \
mac.o debugfs.o
mt76x0-common-y := init.o main.o eeprom.o phy.o
mt76x0u-y := usb.o usb_mcu.o
mt76x0e-y := pci.o pci_mcu.o
# ccflags-y := -DDEBUG
CFLAGS_trace.o := -I$(src)
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/debugfs.h>
#include "mt76x0.h"
#include "eeprom.h"
static int
mt76x0_ampdu_stat_read(struct seq_file *file, void *data)
{
struct mt76x02_dev *dev = file->private;
int i, j;
#define stat_printf(grp, off, name) \
seq_printf(file, #name ":\t%llu\n", dev->stats.grp[off])
stat_printf(rx_stat, 0, rx_crc_err);
stat_printf(rx_stat, 1, rx_phy_err);
stat_printf(rx_stat, 2, rx_false_cca);
stat_printf(rx_stat, 3, rx_plcp_err);
stat_printf(rx_stat, 4, rx_fifo_overflow);
stat_printf(rx_stat, 5, rx_duplicate);
stat_printf(tx_stat, 0, tx_fail_cnt);
stat_printf(tx_stat, 1, tx_bcn_cnt);
stat_printf(tx_stat, 2, tx_success);
stat_printf(tx_stat, 3, tx_retransmit);
stat_printf(tx_stat, 4, tx_zero_len);
stat_printf(tx_stat, 5, tx_underflow);
stat_printf(aggr_stat, 0, non_aggr_tx);
stat_printf(aggr_stat, 1, aggr_tx);
stat_printf(zero_len_del, 0, tx_zero_len_del);
stat_printf(zero_len_del, 1, rx_zero_len_del);
#undef stat_printf
seq_puts(file, "Aggregations stats:\n");
for (i = 0; i < 4; i++) {
for (j = 0; j < 8; j++)
seq_printf(file, "%08llx ",
dev->stats.aggr_n[i * 8 + j]);
seq_putc(file, '\n');
}
seq_printf(file, "recent average AMPDU len: %d\n",
atomic_read(&dev->avg_ampdu_len));
return 0;
}
static int
mt76x0_ampdu_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x0_ampdu_stat_read, inode->i_private);
}
static const struct file_operations fops_ampdu_stat = {
.open = mt76x0_ampdu_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void mt76x0_init_debugfs(struct mt76x02_dev *dev)
{
struct dentry *dir;
dir = mt76_register_debugfs(&dev->mt76);
if (!dir)
return;
debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
}
......@@ -135,9 +135,6 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
u8 val;
if (mt76x0_tssi_enabled(dev))
return 0;
if (chandef->width == NL80211_CHAN_WIDTH_80) {
val = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER) >> 8;
} else if (chandef->width == NL80211_CHAN_WIDTH_40) {
......@@ -160,8 +157,8 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
struct mt76_rate_power *t = &dev->mt76.rate_power;
s8 delta = mt76x0_get_delta(dev);
u16 val, addr;
s8 delta;
memset(t, 0, sizeof(*t));
......@@ -211,6 +208,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
t->vht[7] = s6_to_s8(val);
t->vht[8] = s6_to_s8(val >> 8);
delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev);
mt76x02_add_rate_power_offset(t, delta);
}
......@@ -233,6 +231,20 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
u16 data;
int i;
if (mt76x0_tssi_enabled(dev)) {
s8 target_power;
if (chan->band == NL80211_BAND_5GHZ)
data = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER);
else
data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
info[0] = target_power + mt76x0_get_delta(dev);
info[1] = 0;
return;
}
for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
if (chan_map[i].chan <= chan->hw_value) {
offset = chan_map[i].offset;
......@@ -340,8 +352,6 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
mt76x0_set_freq_offset(dev);
mt76x0_set_temp_offset(dev);
dev->mt76.chainmask = 0x0101;
return 0;
}
......
......@@ -16,7 +16,6 @@
#include "mt76x0.h"
#include "eeprom.h"
#include "trace.h"
#include "mcu.h"
#include "initvals.h"
......@@ -113,7 +112,7 @@ static int mt76x0_init_bbp(struct mt76x02_dev *dev)
{
int ret, i;
ret = mt76x0_wait_bbp_ready(dev);
ret = mt76x0_phy_wait_bbp_ready(dev);
if (ret)
return ret;
......@@ -134,80 +133,28 @@ static int mt76x0_init_bbp(struct mt76x02_dev *dev)
static void mt76x0_init_mac_registers(struct mt76x02_dev *dev)
{
u32 reg;
RANDOM_WRITE(dev, common_mac_reg_table);
mt76x02_set_beacon_offsets(dev);
/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
RANDOM_WRITE(dev, mt76x0_mac_reg_table);
/* Release BBP and MAC reset MAC_SYS_CTRL[1:0] = 0x0 */
reg = mt76_rr(dev, MT_MAC_SYS_CTRL);
reg &= ~0x3;
mt76_wr(dev, MT_MAC_SYS_CTRL, reg);
mt76_clear(dev, MT_MAC_SYS_CTRL, 0x3);
/* Set 0x141C[15:12]=0xF */
reg = mt76_rr(dev, MT_EXT_CCA_CFG);
reg |= 0x0000F000;
mt76_wr(dev, MT_EXT_CCA_CFG, reg);
mt76_set(dev, MT_EXT_CCA_CFG, 0xf000);
mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
/*
TxRing 9 is for Mgmt frame.
TxRing 8 is for In-band command frame.
WMM_RG0_TXQMA: This register setting is for FCE to define the rule of TxRing 9.
WMM_RG1_TXQMA: This register setting is for FCE to define the rule of TxRing 8.
*/
reg = mt76_rr(dev, MT_WMM_CTRL);
reg &= ~0x000003FF;
reg |= 0x00000201;
mt76_wr(dev, MT_WMM_CTRL, reg);
}
static int mt76x0_init_wcid_mem(struct mt76x02_dev *dev)
{
u32 *vals;
int i;
vals = kmalloc(sizeof(*vals) * MT76_N_WCIDS * 2, GFP_KERNEL);
if (!vals)
return -ENOMEM;
for (i = 0; i < MT76_N_WCIDS; i++) {
vals[i * 2] = 0xffffffff;
vals[i * 2 + 1] = 0x00ffffff;
}
mt76_wr_copy(dev, MT_WCID_ADDR_BASE, vals, MT76_N_WCIDS * 2);
kfree(vals);
return 0;
}
static void mt76x0_init_key_mem(struct mt76x02_dev *dev)
{
u32 vals[4] = {};
mt76_wr_copy(dev, MT_SKEY_MODE_BASE_0, vals, ARRAY_SIZE(vals));
}
static int mt76x0_init_wcid_attr_mem(struct mt76x02_dev *dev)
{
u32 *vals;
int i;
vals = kmalloc(sizeof(*vals) * MT76_N_WCIDS * 2, GFP_KERNEL);
if (!vals)
return -ENOMEM;
for (i = 0; i < MT76_N_WCIDS * 2; i++)
vals[i] = 1;
mt76_wr_copy(dev, MT_WCID_ATTR_BASE, vals, MT76_N_WCIDS * 2);
kfree(vals);
return 0;
* tx_ring 9 is for mgmt frame
* tx_ring 8 is for in-band command frame.
* WMM_RG0_TXQMA: this register setting is for FCE to
* define the rule of tx_ring 9
* WMM_RG1_TXQMA: this register setting is for FCE to
* define the rule of tx_ring 8
*/
mt76_rmw(dev, MT_WMM_CTRL, 0x3ff, 0x201);
}
static void mt76x0_reset_counters(struct mt76x02_dev *dev)
......@@ -270,7 +217,7 @@ EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
int mt76x0_init_hardware(struct mt76x02_dev *dev)
{
int ret;
int ret, i, k;
if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
return -EIO;
......@@ -280,7 +227,7 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
return -ETIMEDOUT;
mt76x0_reset_csr_bbp(dev);
ret = mt76x02_mcu_function_select(dev, Q_SELECT, 1, false);
ret = mt76x02_mcu_function_select(dev, Q_SELECT, 1);
if (ret)
return ret;
......@@ -295,20 +242,12 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
ret = mt76x0_init_wcid_mem(dev);
if (ret)
return ret;
for (i = 0; i < 16; i++)
for (k = 0; k < 4; k++)
mt76x02_mac_shared_key_setup(dev, i, k, NULL);
mt76x0_init_key_mem(dev);
ret = mt76x0_init_wcid_attr_mem(dev);
if (ret)
return ret;
mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
MT_BEACON_TIME_CFG_SYNC_MODE |
MT_BEACON_TIME_CFG_TBTT_EN |
MT_BEACON_TIME_CFG_BEACON_TX));
for (i = 0; i < 256; i++)
mt76x02_mac_wcid_setup(dev, i, 0, NULL);
mt76x0_reset_counters(dev);
......@@ -317,6 +256,7 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
return ret;
mt76x0_phy_init(dev);
mt76x02_init_beacon_config(dev);
return 0;
}
......@@ -339,7 +279,6 @@ mt76x0_alloc_device(struct device *pdev,
dev = container_of(mdev, struct mt76x02_dev, mt76);
mutex_init(&dev->phy_mutex);
atomic_set(&dev->avg_ampdu_len, 1);
return dev;
}
......@@ -347,49 +286,21 @@ EXPORT_SYMBOL_GPL(mt76x0_alloc_device);
int mt76x0_register_device(struct mt76x02_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_hw *hw = mdev->hw;
struct wiphy *wiphy = hw->wiphy;
int ret;
/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
* entry no. 1 like it does in the vendor driver.
*/
mdev->wcid_mask[0] |= 1;
/* init fake wcid for monitor interfaces */
mdev->global_wcid.idx = 0xff;
mdev->global_wcid.hw_key_idx = -1;
/* init antenna configuration */
mdev->antenna_mask = 1;
hw->queues = 4;
hw->max_rates = 1;
hw->max_report_rates = 7;
hw->max_rate_tries = 1;
hw->extra_tx_headroom = 2;
if (mt76_is_usb(dev))
hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) +
MT_DMA_HDR_LEN;
hw->sta_data_size = sizeof(struct mt76x02_sta);
hw->vif_data_size = sizeof(struct mt76x02_vif);
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
INIT_DELAYED_WORK(&dev->mac_work, mt76x0_mac_work);
mt76x02_init_device(dev);
mt76x02_config_mac_addr_list(dev);
ret = mt76_register_device(mdev, true, mt76x02_rates,
ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
ARRAY_SIZE(mt76x02_rates));
if (ret)
return ret;
/* overwrite unsupported features */
if (mdev->cap.has_5ghz)
if (dev->mt76.cap.has_5ghz)
mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);
mt76x0_init_debugfs(dev);
mt76x02_init_debugfs(dev);
return 0;
}
......
......@@ -37,14 +37,14 @@ static const struct mt76_reg_pair common_mac_reg_table[] = {
{ MT_PBF_RX_MAX_PCNT, 0x0000fe9f },
{ MT_TX_RETRY_CFG, 0x47d01f0f },
{ MT_AUTO_RSP_CFG, 0x00000013 },
{ MT_CCK_PROT_CFG, 0x05740003 },
{ MT_OFDM_PROT_CFG, 0x05740003 },
{ MT_CCK_PROT_CFG, 0x07f40003 },
{ MT_OFDM_PROT_CFG, 0x07f42004 },
{ MT_PBF_CFG, 0x00f40006 },
{ MT_WPDMA_GLO_CFG, 0x00000030 },
{ MT_GF20_PROT_CFG, 0x01744004 },
{ MT_GF40_PROT_CFG, 0x03f44084 },
{ MT_MM20_PROT_CFG, 0x01744004 },
{ MT_MM40_PROT_CFG, 0x03f54084 },
{ MT_GF20_PROT_CFG, 0x01742004 },
{ MT_GF40_PROT_CFG, 0x03f42084 },
{ MT_MM20_PROT_CFG, 0x01742004 },
{ MT_MM40_PROT_CFG, 0x03f42084 },
{ MT_TXOP_CTRL_CFG, 0x0000583f },
{ MT_TX_RTS_CFG, 0x00092b20 },
{ MT_EXP_ACK_TIME, 0x002400ca },
......@@ -85,6 +85,9 @@ static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
{ MT_HT_CTRL_CFG, 0x000001FF },
{ MT_TXOP_HLDR_ET, 0x00000000 },
{ MT_PN_PAD_MODE, 0x00000003 },
{ MT_TX_PROT_CFG6, 0xe3f42004 },
{ MT_TX_PROT_CFG7, 0xe3f42084 },
{ MT_TX_PROT_CFG8, 0xe3f42104 },
};
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
......
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/etherdevice.h>
#include "mt76x0.h"
#include "trace.h"
void mt76x0_mac_set_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];
bool ht_rts[4] = {};
int i;
prot[0] = MT_PROT_NAV_SHORT |
MT_PROT_TXOP_ALLOW_ALL |
MT_PROT_RTS_THR_EN;
prot[1] = prot[0];
if (legacy_prot)
prot[1] |= MT_PROT_CTRL_CTS2SELF;
prot[2] = prot[4] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_BW20;
prot[3] = prot[5] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_ALL;
if (legacy_prot) {
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;
} else {
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;
}
switch (mode) {
case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
break;
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
break;
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
ht_rts[1] = ht_rts[3] = true;
break;
case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
break;
}
if (non_gf)
ht_rts[2] = ht_rts[3] = true;
for (i = 0; i < 4; i++)
if (ht_rts[i])
prot[i + 2] |= MT_PROT_CTRL_RTS_CTS;
for (i = 0; i < 6; i++)
mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
}
void mt76x0_mac_set_short_preamble(struct mt76x02_dev *dev, bool short_preamb)
{
if (short_preamb)
mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
else
mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
}
void mt76x0_mac_config_tsf(struct mt76x02_dev *dev, bool enable, int interval)
{
u32 val = mt76_rr(dev, MT_BEACON_TIME_CFG);
val &= ~(MT_BEACON_TIME_CFG_TIMER_EN |
MT_BEACON_TIME_CFG_SYNC_MODE |
MT_BEACON_TIME_CFG_TBTT_EN);
if (!enable) {
mt76_wr(dev, MT_BEACON_TIME_CFG, val);
return;
}
val &= ~MT_BEACON_TIME_CFG_INTVAL;
val |= FIELD_PREP(MT_BEACON_TIME_CFG_INTVAL, interval << 4) |
MT_BEACON_TIME_CFG_TIMER_EN |
MT_BEACON_TIME_CFG_SYNC_MODE |
MT_BEACON_TIME_CFG_TBTT_EN;
}
static void mt76x0_check_mac_err(struct mt76x02_dev *dev)
{
u32 val = mt76_rr(dev, 0x10f4);
if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5))))
return;
dev_err(dev->mt76.dev, "Error: MAC specific condition occurred\n");
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
udelay(10);
mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
}
void mt76x0_mac_work(struct work_struct *work)
{
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
mac_work.work);
struct {
u32 addr_base;
u32 span;
u64 *stat_base;
} spans[] = {
{ MT_RX_STAT_0, 3, dev->stats.rx_stat },
{ MT_TX_STA_0, 3, dev->stats.tx_stat },
{ MT_TX_AGG_STAT, 1, dev->stats.aggr_stat },
{ MT_MPDU_DENSITY_CNT, 1, dev->stats.zero_len_del },
{ MT_TX_AGG_CNT_BASE0, 8, &dev->stats.aggr_n[0] },
{ MT_TX_AGG_CNT_BASE1, 8, &dev->stats.aggr_n[16] },
};
u32 sum, n;
int i, j, k;
/* Note: using MCU_RANDOM_READ is actually slower then reading all the
* registers by hand. MCU takes ca. 20ms to complete read of 24
* registers while reading them one by one will takes roughly
* 24*200us =~ 5ms.
*/
k = 0;
n = 0;
sum = 0;
for (i = 0; i < ARRAY_SIZE(spans); i++)
for (j = 0; j < spans[i].span; j++) {
u32 val = mt76_rr(dev, spans[i].addr_base + j * 4);
spans[i].stat_base[j * 2] += val & 0xffff;
spans[i].stat_base[j * 2 + 1] += val >> 16;
/* Calculate average AMPDU length */
if (spans[i].addr_base != MT_TX_AGG_CNT_BASE0 &&
spans[i].addr_base != MT_TX_AGG_CNT_BASE1)
continue;
n += (val >> 16) + (val & 0xffff);
sum += (val & 0xffff) * (1 + k * 2) +
(val >> 16) * (2 + k * 2);
k++;
}
atomic_set(&dev->avg_ampdu_len, n ? DIV_ROUND_CLOSEST(sum, n) : 1);
mt76x0_check_mac_err(dev);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, 10 * HZ);
}
void mt76x0_mac_set_ampdu_factor(struct mt76x02_dev *dev)
{
struct ieee80211_sta *sta;
struct mt76_wcid *wcid;
void *msta;
u8 min_factor = 3;
int i;
rcu_read_lock();
for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) {
wcid = rcu_dereference(dev->mt76.wcid[i]);
if (!wcid)
continue;
msta = container_of(wcid, struct mt76x02_sta, wcid);
sta = container_of(msta, struct ieee80211_sta, drv_priv);
min_factor = min(min_factor, sta->ht_cap.ampdu_factor);
}
rcu_read_unlock();
mt76_wr(dev, MT_MAX_LEN_CFG, 0xa0fff |
FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor));
}
......@@ -22,9 +22,23 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
int ret;
cancel_delayed_work_sync(&dev->cal_work);
if (mt76_is_mmio(dev)) {
tasklet_disable(&dev->pre_tbtt_tasklet);
tasklet_disable(&dev->dfs_pd.dfs_tasklet);
}
mt76_set_channel(&dev->mt76);
ret = mt76x0_phy_set_channel(dev, chandef);
/* channel cycle counters read-and-clear */
mt76_rr(dev, MT_CH_IDLE);
mt76_rr(dev, MT_CH_BUSY);
if (mt76_is_mmio(dev)) {
mt76x02_dfs_init_params(dev);
tasklet_enable(&dev->pre_tbtt_tasklet);
tasklet_enable(&dev->dfs_pd.dfs_tasklet);
}
mt76_txq_schedule_all(&dev->mt76);
return ret;
......@@ -64,89 +78,3 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
return ret;
}
EXPORT_SYMBOL_GPL(mt76x0_config);
static void
mt76x0_addr_wr(struct mt76x02_dev *dev, const u32 offset, const u8 *addr)
{
mt76_wr(dev, offset, get_unaligned_le32(addr));
mt76_wr(dev, offset + 4, addr[4] | addr[5] << 8);
}
void mt76x0_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed)
{
struct mt76x02_dev *dev = hw->priv;
mutex_lock(&dev->mt76.mutex);
if (changed & BSS_CHANGED_BSSID) {
mt76x0_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid);
/* Note: this is a hack because beacon_int is not changed
* on leave nor is any more appropriate event generated.
* rt2x00 doesn't seem to be bothered though.
*/
if (is_zero_ether_addr(info->bssid))
mt76x0_mac_config_tsf(dev, false, 0);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
mt76_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);
mt76_wr(dev, MT_VHT_HT_FBK_CFG0, 0x65432100);
mt76_wr(dev, MT_VHT_HT_FBK_CFG1, 0xedcba980);
mt76_wr(dev, MT_LG_FBK_CFG0, 0xedcba988);
mt76_wr(dev, MT_LG_FBK_CFG1, 0x00002100);
}
if (changed & BSS_CHANGED_BEACON_INT)
mt76x0_mac_config_tsf(dev, true, info->beacon_int);
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
mt76x0_mac_set_protection(dev, info->use_cts_prot,
info->ht_operation_mode);
if (changed & BSS_CHANGED_ERP_PREAMBLE)
mt76x0_mac_set_short_preamble(dev, info->use_short_preamble);
if (changed & BSS_CHANGED_ERP_SLOT) {
int slottime = info->use_short_slot ? 9 : 20;
mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG,
MT_BKOFF_SLOT_CFG_SLOTTIME, slottime);
}
if (changed & BSS_CHANGED_ASSOC)
mt76x0_phy_recalibrate_after_assoc(dev);
mutex_unlock(&dev->mt76.mutex);
}
EXPORT_SYMBOL_GPL(mt76x0_bss_info_changed);
void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac_addr)
{
struct mt76x02_dev *dev = hw->priv;
set_bit(MT76_SCANNING, &dev->mt76.state);
}
EXPORT_SYMBOL_GPL(mt76x0_sw_scan);
void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt76x02_dev *dev = hw->priv;
clear_bit(MT76_SCANNING, &dev->mt76.state);
}
EXPORT_SYMBOL_GPL(mt76x0_sw_scan_complete);
int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
struct mt76x02_dev *dev = hw->priv;
mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value);
return 0;
}
EXPORT_SYMBOL_GPL(mt76x0_set_rts_threshold);
......@@ -28,18 +28,26 @@
#include "../mt76x02.h"
#include "eeprom.h"
#define MT_CALIBRATE_INTERVAL (4 * HZ)
#define MT7610E_FIRMWARE "mediatek/mt7610e.bin"
#define MT7650E_FIRMWARE "mediatek/mt7650e.bin"
#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
#define MT_USB_AGGR_SIZE_LIMIT 21 /* * 1024B */
#define MT_USB_AGGR_TIMEOUT 0x80 /* * 33ns */
static inline bool is_mt7610e(struct mt76x02_dev *dev)
{
/* TODO */
return false;
if (!mt76_is_mmio(dev))
return false;
return mt76_chip(&dev->mt76) == 0x7610;
}
void mt76x0_init_debugfs(struct mt76x02_dev *dev);
static inline bool is_mt7630(struct mt76x02_dev *dev)
{
return mt76_chip(&dev->mt76) == 0x7630;
}
/* Init */
struct mt76x02_dev *
......@@ -54,30 +62,12 @@ int mt76x0_mac_start(struct mt76x02_dev *dev);
void mt76x0_mac_stop(struct mt76x02_dev *dev);
int mt76x0_config(struct ieee80211_hw *hw, u32 changed);
void mt76x0_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed);
void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac_addr);
void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
/* PHY */
void mt76x0_phy_init(struct mt76x02_dev *dev);
int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev);
int mt76x0_phy_wait_bbp_ready(struct mt76x02_dev *dev);
int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef);
void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev);
void mt76x0_phy_set_txpower(struct mt76x02_dev *dev);
void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on);
/* MAC */
void mt76x0_mac_work(struct work_struct *work);
void mt76x0_mac_set_protection(struct mt76x02_dev *dev, bool legacy_prot,
int ht_mode);
void mt76x0_mac_set_short_preamble(struct mt76x02_dev *dev, bool short_preamb);
void mt76x0_mac_config_tsf(struct mt76x02_dev *dev, bool enable, int interval);
void mt76x0_mac_set_ampdu_factor(struct mt76x02_dev *dev);
#endif
......@@ -68,6 +68,19 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
mutex_unlock(&dev->mt76.mutex);
}
static void
mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
}
static int
mt76x0e_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
bool set)
{
return 0;
}
static const struct ieee80211_ops mt76x0e_ops = {
.tx = mt76x02_tx,
.start = mt76x0e_start,
......@@ -76,15 +89,22 @@ static const struct ieee80211_ops mt76x0e_ops = {
.remove_interface = mt76x02_remove_interface,
.config = mt76x0_config,
.configure_filter = mt76x02_configure_filter,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
.bss_info_changed = mt76x02_bss_info_changed,
.sta_state = mt76_sta_state,
.set_key = mt76x02_set_key,
.conf_tx = mt76x02_conf_tx,
.sw_scan_start = mt76x0_sw_scan,
.sw_scan_complete = mt76x0_sw_scan_complete,
.sw_scan_start = mt76x02_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
.ampdu_action = mt76x02_ampdu_action,
.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,
.flush = mt76x0e_flush,
.set_tim = mt76x0e_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
.set_coverage_class = mt76x02_set_coverage_class,
.set_rts_threshold = mt76x02_set_rts_threshold,
};
static int mt76x0e_register_device(struct mt76x02_dev *dev)
......@@ -135,10 +155,14 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
.tx_complete_skb = mt76x02_tx_complete_skb,
.rx_skb = mt76x02_queue_rx_skb,
.rx_poll_complete = mt76x02_rx_poll_complete,
.sta_ps = mt76x02_sta_ps,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct mt76x02_dev *dev;
int ret;
......@@ -185,6 +209,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static void mt76x0e_cleanup(struct mt76x02_dev *dev)
{
clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
tasklet_disable(&dev->pre_tbtt_tasklet);
mt76x0_chip_onoff(dev, false, false);
mt76x0e_stop_hw(dev);
mt76x02_dma_cleanup(dev);
......@@ -209,6 +234,8 @@ static const struct pci_device_id mt76x0e_device_table[] = {
};
MODULE_DEVICE_TABLE(pci, mt76x0e_device_table);
MODULE_FIRMWARE(MT7610E_FIRMWARE);
MODULE_FIRMWARE(MT7650E_FIRMWARE);
MODULE_LICENSE("Dual BSD/GPL");
static struct pci_driver mt76x0e_driver = {
......
......@@ -19,9 +19,6 @@
#include "mt76x0.h"
#include "mcu.h"
#define MT7610E_FIRMWARE "mediatek/mt7610e.bin"
#define MT7650E_FIRMWARE "mediatek/mt7650e.bin"
#define MT_MCU_IVB_ADDR (MT_MCU_ILM_ADDR + 0x54000 - MT_MCU_IVB_SIZE)
static int mt76x0e_load_firmware(struct mt76x02_dev *dev)
......@@ -130,7 +127,6 @@ static int mt76x0e_load_firmware(struct mt76x02_dev *dev)
int mt76x0e_mcu_init(struct mt76x02_dev *dev)
{
static const struct mt76_mcu_ops mt76x0e_mcu_ops = {
.mcu_msg_alloc = mt76x02_mcu_msg_alloc,
.mcu_send_msg = mt76x02_mcu_msg_send,
};
int err;
......
......@@ -30,6 +30,23 @@
#define MT_RF_BANK(offset) (offset >> 16)
#define MT_RF_REG(offset) (offset & 0xff)
#define MT_RF_VCO_BP_CLOSE_LOOP BIT(3)
#define MT_RF_VCO_BP_CLOSE_LOOP_MASK GENMASK(3, 0)
#define MT_RF_VCO_CAL_MASK GENMASK(2, 0)
#define MT_RF_START_TIME 0x3
#define MT_RF_START_TIME_MASK GENMASK(2, 0)
#define MT_RF_SETTLE_TIME_MASK GENMASK(6, 4)
#define MT_RF_PLL_DEN_MASK GENMASK(4, 0)
#define MT_RF_PLL_K_MASK GENMASK(4, 0)
#define MT_RF_SDM_RESET_MASK BIT(7)
#define MT_RF_SDM_MASH_PRBS_MASK GENMASK(6, 2)
#define MT_RF_SDM_BP_MASK BIT(1)
#define MT_RF_ISI_ISO_MASK GENMASK(7, 6)
#define MT_RF_PFD_DLY_MASK GENMASK(5, 4)
#define MT_RF_CLK_SEL_MASK GENMASK(3, 2)
#define MT_RF_XO_DIV_MASK GENMASK(1, 0)
struct mt76x0_bbp_switch_item {
u16 bw_band;
struct mt76_reg_pair reg_pair;
......
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "trace.h"
#endif
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#if !defined(__MT76X0U_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define __MT76X0U_TRACE_H
#include <linux/tracepoint.h>
#include "mt76x0.h"
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mt76x0
#define MAXNAME 32
#define DEV_ENTRY __array(char, wiphy_name, 32)
#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \
wiphy_name(dev->hw->wiphy), MAXNAME)
#define DEV_PR_FMT "%s "
#define DEV_PR_ARG __entry->wiphy_name
#define REG_ENTRY __field(u32, reg) __field(u32, val)
#define REG_ASSIGN __entry->reg = reg; __entry->val = val
#define REG_PR_FMT "%04x=%08x"
#define REG_PR_ARG __entry->reg, __entry->val
DECLARE_EVENT_CLASS(dev_reg_evt,
TP_PROTO(struct mt76_dev *dev, u32 reg, u32 val),
TP_ARGS(dev, reg, val),
TP_STRUCT__entry(
DEV_ENTRY
REG_ENTRY
),
TP_fast_assign(
DEV_ASSIGN;
REG_ASSIGN;
),
TP_printk(
DEV_PR_FMT REG_PR_FMT,
DEV_PR_ARG, REG_PR_ARG
)
);
DEFINE_EVENT(dev_reg_evt, mt76x0_reg_read,
TP_PROTO(struct mt76_dev *dev, u32 reg, u32 val),
TP_ARGS(dev, reg, val)
);
DEFINE_EVENT(dev_reg_evt, mt76x0_reg_write,
TP_PROTO(struct mt76_dev *dev, u32 reg, u32 val),
TP_ARGS(dev, reg, val)
);
TRACE_EVENT(mt76x0_submit_urb,
TP_PROTO(struct mt76_dev *dev, struct urb *u),
TP_ARGS(dev, u),
TP_STRUCT__entry(
DEV_ENTRY __field(unsigned, pipe) __field(u32, len)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->pipe = u->pipe;
__entry->len = u->transfer_buffer_length;
),
TP_printk(DEV_PR_FMT "p:%08x len:%u",
DEV_PR_ARG, __entry->pipe, __entry->len)
);
#define trace_mt76x0_submit_urb_sync(__dev, __pipe, __len) ({ \
struct urb u; \
u.pipe = __pipe; \
u.transfer_buffer_length = __len; \
trace_mt76x0_submit_urb(__dev, &u); \
})
TRACE_EVENT(mt76x0_mcu_msg_send,
TP_PROTO(struct mt76_dev *dev,
struct sk_buff *skb, u32 csum, bool resp),
TP_ARGS(dev, skb, csum, resp),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, info)
__field(u32, csum)
__field(bool, resp)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->info = *(u32 *)skb->data;
__entry->csum = csum;
__entry->resp = resp;
),
TP_printk(DEV_PR_FMT "i:%08x c:%08x r:%d",
DEV_PR_ARG, __entry->info, __entry->csum, __entry->resp)
);
TRACE_EVENT(mt76x0_vend_req,
TP_PROTO(struct mt76_dev *dev, unsigned pipe, u8 req, u8 req_type,
u16 val, u16 offset, void *buf, size_t buflen, int ret),
TP_ARGS(dev, pipe, req, req_type, val, offset, buf, buflen, ret),
TP_STRUCT__entry(
DEV_ENTRY
__field(unsigned, pipe) __field(u8, req) __field(u8, req_type)
__field(u16, val) __field(u16, offset) __field(void*, buf)
__field(int, buflen) __field(int, ret)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->pipe = pipe;
__entry->req = req;
__entry->req_type = req_type;
__entry->val = val;
__entry->offset = offset;
__entry->buf = buf;
__entry->buflen = buflen;
__entry->ret = ret;
),
TP_printk(DEV_PR_FMT
"%d p:%08x req:%02hhx %02hhx val:%04hx %04hx buf:%d %d",
DEV_PR_ARG, __entry->ret, __entry->pipe, __entry->req,
__entry->req_type, __entry->val, __entry->offset,
!!__entry->buf, __entry->buflen)
);
DECLARE_EVENT_CLASS(dev_rf_reg_evt,
TP_PROTO(struct mt76_dev *dev, u8 bank, u8 reg, u8 val),
TP_ARGS(dev, bank, reg, val),
TP_STRUCT__entry(
DEV_ENTRY
__field(u8, bank)
__field(u8, reg)
__field(u8, val)
),
TP_fast_assign(
DEV_ASSIGN;
REG_ASSIGN;
__entry->bank = bank;
),
TP_printk(
DEV_PR_FMT "%02hhx:%02hhx=%02hhx",
DEV_PR_ARG, __entry->bank, __entry->reg, __entry->val
)
);
DEFINE_EVENT(dev_rf_reg_evt, mt76x0_rf_read,
TP_PROTO(struct mt76_dev *dev, u8 bank, u8 reg, u8 val),
TP_ARGS(dev, bank, reg, val)
);
DEFINE_EVENT(dev_rf_reg_evt, mt76x0_rf_write,
TP_PROTO(struct mt76_dev *dev, u8 bank, u8 reg, u8 val),
TP_ARGS(dev, bank, reg, val)
);
DECLARE_EVENT_CLASS(dev_simple_evt,
TP_PROTO(struct mt76_dev *dev, u8 val),
TP_ARGS(dev, val),
TP_STRUCT__entry(
DEV_ENTRY
__field(u8, val)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->val = val;
),
TP_printk(
DEV_PR_FMT "%02hhx", DEV_PR_ARG, __entry->val
)
);
TRACE_EVENT(mt76x0_rx,
TP_PROTO(struct mt76_dev *dev, struct mt76x02_rxwi *rxwi, u32 f),
TP_ARGS(dev, rxwi, f),
TP_STRUCT__entry(
DEV_ENTRY
__field_struct(struct mt76x02_rxwi, rxwi)
__field(u32, fce_info)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->rxwi = *rxwi;
__entry->fce_info = f;
),
TP_printk(DEV_PR_FMT "rxi:%08x ctl:%08x", DEV_PR_ARG,
le32_to_cpu(__entry->rxwi.rxinfo),
le32_to_cpu(__entry->rxwi.ctl))
);
TRACE_EVENT(mt76x0_tx,
TP_PROTO(struct mt76_dev *dev, struct sk_buff *skb,
struct mt76x02_sta *sta, struct mt76x02_txwi *h),
TP_ARGS(dev, skb, sta, h),
TP_STRUCT__entry(
DEV_ENTRY
__field_struct(struct mt76x02_txwi, h)
__field(struct sk_buff *, skb)
__field(struct mt76x02_sta *, sta)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->h = *h;
__entry->skb = skb;
__entry->sta = sta;
),
TP_printk(DEV_PR_FMT "skb:%p sta:%p flg:%04hx rate:%04hx "
"ack:%02hhx wcid:%02hhx len_ctl:%05hx", DEV_PR_ARG,
__entry->skb, __entry->sta,
le16_to_cpu(__entry->h.flags),
le16_to_cpu(__entry->h.rate),
__entry->h.ack_ctl, __entry->h.wcid,
le16_to_cpu(__entry->h.len_ctl))
);
TRACE_EVENT(mt76x0_tx_dma_done,
TP_PROTO(struct mt76_dev *dev, struct sk_buff *skb),
TP_ARGS(dev, skb),
TP_STRUCT__entry(
DEV_ENTRY
__field(struct sk_buff *, skb)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->skb = skb;
),
TP_printk(DEV_PR_FMT "%p", DEV_PR_ARG, __entry->skb)
);
TRACE_EVENT(mt76x0_tx_status_cleaned,
TP_PROTO(struct mt76_dev *dev, int cleaned),
TP_ARGS(dev, cleaned),
TP_STRUCT__entry(
DEV_ENTRY
__field(int, cleaned)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->cleaned = cleaned;
),
TP_printk(DEV_PR_FMT "%d", DEV_PR_ARG, __entry->cleaned)
);
TRACE_EVENT(mt76x0_tx_status,
TP_PROTO(struct mt76_dev *dev, u32 stat1, u32 stat2),
TP_ARGS(dev, stat1, stat2),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, stat1) __field(u32, stat2)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->stat1 = stat1;
__entry->stat2 = stat2;
),
TP_printk(DEV_PR_FMT "%08x %08x",
DEV_PR_ARG, __entry->stat1, __entry->stat2)
);
TRACE_EVENT(mt76x0_rx_dma_aggr,
TP_PROTO(struct mt76_dev *dev, int cnt, bool paged),
TP_ARGS(dev, cnt, paged),
TP_STRUCT__entry(
DEV_ENTRY
__field(u8, cnt)
__field(bool, paged)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->cnt = cnt;
__entry->paged = paged;
),
TP_printk(DEV_PR_FMT "cnt:%d paged:%d",
DEV_PR_ARG, __entry->cnt, __entry->paged)
);
DEFINE_EVENT(dev_simple_evt, mt76x0_set_key,
TP_PROTO(struct mt76_dev *dev, u8 val),
TP_ARGS(dev, val)
);
TRACE_EVENT(mt76x0_set_shared_key,
TP_PROTO(struct mt76_dev *dev, u8 vid, u8 key),
TP_ARGS(dev, vid, key),
TP_STRUCT__entry(
DEV_ENTRY
__field(u8, vid)
__field(u8, key)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->vid = vid;
__entry->key = key;
),
TP_printk(DEV_PR_FMT "phy:%02hhx off:%02hhx",
DEV_PR_ARG, __entry->vid, __entry->key)
);
#endif
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
......@@ -17,7 +17,6 @@
#include "mt76x0.h"
#include "mcu.h"
#include "trace.h"
#include "../mt76x02_usb.h"
static struct usb_device_id mt76x0_device_table[] = {
......@@ -117,6 +116,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)
if (ret)
goto out;
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
MT_CALIBRATE_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
......@@ -145,17 +145,17 @@ static const struct ieee80211_ops mt76x0u_ops = {
.remove_interface = mt76x02_remove_interface,
.config = mt76x0_config,
.configure_filter = mt76x02_configure_filter,
.bss_info_changed = mt76x0_bss_info_changed,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
.bss_info_changed = mt76x02_bss_info_changed,
.sta_state = mt76_sta_state,
.set_key = mt76x02_set_key,
.conf_tx = mt76x02_conf_tx,
.sw_scan_start = mt76x0_sw_scan,
.sw_scan_complete = mt76x0_sw_scan_complete,
.sw_scan_start = mt76x02_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
.ampdu_action = mt76x02_ampdu_action,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.set_rts_threshold = mt76x0_set_rts_threshold,
.set_rts_threshold = mt76x02_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
.get_txpower = mt76x02_get_txpower,
};
static int mt76x0u_register_device(struct mt76x02_dev *dev)
......@@ -218,6 +218,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
.tx_complete_skb = mt76x02u_tx_complete_skb,
.tx_status_data = mt76x02_tx_status_data,
.rx_skb = mt76x02_queue_rx_skb,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct mt76x02_dev *dev;
......@@ -337,6 +339,8 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
}
MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
MODULE_FIRMWARE(MT7610E_FIRMWARE);
MODULE_FIRMWARE(MT7610U_FIRMWARE);
MODULE_LICENSE("GPL");
static struct usb_driver mt76x0_driver = {
......
......@@ -22,7 +22,6 @@
#define MCU_FW_URB_MAX_PAYLOAD 0x38f8
#define MCU_FW_URB_SIZE (MCU_FW_URB_MAX_PAYLOAD + 12)
#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
static int
mt76x0u_upload_firmware(struct mt76x02_dev *dev,
......@@ -75,6 +74,24 @@ mt76x0u_upload_firmware(struct mt76x02_dev *dev,
return err;
}
static int mt76x0_get_firmware(struct mt76x02_dev *dev,
const struct firmware **fw)
{
int err;
/* try to load mt7610e fw if available
* otherwise fall back to mt7610u one
*/
err = firmware_request_nowarn(fw, MT7610E_FIRMWARE, dev->mt76.dev);
if (err) {
dev_info(dev->mt76.dev, "%s not found, switching to %s",
MT7610E_FIRMWARE, MT7610U_FIRMWARE);
return request_firmware(fw, MT7610U_FIRMWARE,
dev->mt76.dev);
}
return 0;
}
static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
{
const struct firmware *fw;
......@@ -88,7 +105,7 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
if (mt76x0_firmware_running(dev))
return 0;
ret = request_firmware(&fw, MT7610U_FIRMWARE, dev->mt76.dev);
ret = mt76x0_get_firmware(dev, &fw);
if (ret)
return ret;
......@@ -171,5 +188,3 @@ int mt76x0u_mcu_init(struct mt76x02_dev *dev)
return 0;
}
MODULE_FIRMWARE(MT7610U_FIRMWARE);
......@@ -26,13 +26,7 @@
#include "mt76x02_dfs.h"
#include "mt76x02_dma.h"
struct mt76x02_mac_stats {
u64 rx_stat[6];
u64 tx_stat[6];
u64 aggr_stat[2];
u64 aggr_n[32];
u64 zero_len_del[2];
};
#define MT_CALIBRATE_INTERVAL HZ
#define MT_MAX_CHAINS 2
struct mt76x02_rx_freq_cal {
......@@ -63,6 +57,10 @@ struct mt76x02_calibration {
bool tssi_comp_pending;
bool dpd_cal_done;
bool channel_cal_done;
bool gain_init_done;
int tssi_target;
s8 tssi_dc;
};
struct mt76x02_dev {
......@@ -82,8 +80,6 @@ struct mt76x02_dev {
struct delayed_work cal_work;
struct delayed_work mac_work;
struct mt76x02_mac_stats stats;
atomic_t avg_ampdu_len;
u32 aggr_stats[32];
struct sk_buff *beacons[8];
......@@ -109,14 +105,16 @@ struct mt76x02_dev {
extern struct ieee80211_rate mt76x02_rates[12];
void mt76x02_init_device(struct mt76x02_dev *dev);
void mt76x02_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags, u64 multicast);
int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt76x02_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev);
void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
unsigned int idx);
int mt76x02_add_interface(struct ieee80211_hw *hw,
......@@ -139,9 +137,12 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev,
s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr,
s8 max_txpwr_adj);
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,
s16 coverage_class);
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
int mt76x02_insert_hdr_pad(struct sk_buff *skb);
void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb);
bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
......@@ -153,12 +154,24 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
struct sk_buff *skb, struct mt76_queue *q,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
u32 *tx_info);
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,
struct ieee80211_bss_conf *info, u32 changed);
extern const u16 mt76x02_beacon_offsets[16];
void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev);
void mt76x02_init_beacon_config(struct mt76x02_dev *dev);
void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set);
void mt76x02_mac_start(struct mt76x02_dev *dev);
void mt76x02_init_debugfs(struct mt76x02_dev *dev);
static inline bool is_mt76x2(struct mt76x02_dev *dev)
{
return mt76_chip(&dev->mt76) == 0x7612 ||
......
......@@ -15,10 +15,10 @@
*/
#include <linux/debugfs.h>
#include "mt76x2.h"
#include "mt76x02.h"
static int
mt76x2_ampdu_stat_read(struct seq_file *file, void *data)
mt76x02_ampdu_stat_read(struct seq_file *file, void *data)
{
struct mt76x02_dev *dev = file->private;
int i, j;
......@@ -42,9 +42,9 @@ mt76x2_ampdu_stat_read(struct seq_file *file, void *data)
}
static int
mt76x2_ampdu_stat_open(struct inode *inode, struct file *f)
mt76x02_ampdu_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x2_ampdu_stat_read, inode->i_private);
return single_open(f, mt76x02_ampdu_stat_read, inode->i_private);
}
static int read_txpower(struct seq_file *file, void *data)
......@@ -59,14 +59,14 @@ static int read_txpower(struct seq_file *file, void *data)
}
static const struct file_operations fops_ampdu_stat = {
.open = mt76x2_ampdu_stat_open,
.open = mt76x02_ampdu_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int
mt76x2_dfs_stat_read(struct seq_file *file, void *data)
mt76x02_dfs_stat_read(struct seq_file *file, void *data)
{
struct mt76x02_dev *dev = file->private;
struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
......@@ -92,13 +92,13 @@ mt76x2_dfs_stat_read(struct seq_file *file, void *data)
}
static int
mt76x2_dfs_stat_open(struct inode *inode, struct file *f)
mt76x02_dfs_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x2_dfs_stat_read, inode->i_private);
return single_open(f, mt76x02_dfs_stat_read, inode->i_private);
}
static const struct file_operations fops_dfs_stat = {
.open = mt76x2_dfs_stat_open,
.open = mt76x02_dfs_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
......@@ -116,7 +116,7 @@ static int read_agc(struct seq_file *file, void *data)
return 0;
}
void mt76x2_init_debugfs(struct mt76x02_dev *dev)
void mt76x02_init_debugfs(struct mt76x02_dev *dev)
{
struct dentry *dir;
......@@ -134,4 +134,4 @@ void mt76x2_init_debugfs(struct mt76x02_dev *dev)
debugfs_create_devm_seqfile(dev->mt76.dev, "agc", dir, read_agc);
}
EXPORT_SYMBOL_GPL(mt76x2_init_debugfs);
EXPORT_SYMBOL_GPL(mt76x02_init_debugfs);
......@@ -137,4 +137,9 @@ struct mt76x02_dfs_pattern_detector {
struct tasklet_struct dfs_tasklet;
};
void mt76x02_dfs_init_params(struct mt76x02_dev *dev);
void mt76x02_dfs_init_detector(struct mt76x02_dev *dev);
void mt76x02_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request);
void mt76x02_phy_dfs_adjust_agc(struct mt76x02_dev *dev);
#endif /* __MT76x02_DFS_H */
......@@ -53,6 +53,18 @@ mt76x02_efuse_read(struct mt76x02_dev *dev, u16 addr, u8 *data,
return 0;
}
int mt76x02_eeprom_copy(struct mt76x02_dev *dev,
enum mt76x02_eeprom_field field,
void *dest, int len)
{
if (field + len > dev->mt76.eeprom.size)
return -1;
memcpy(dest, dev->mt76.eeprom.data + field, len);
return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_eeprom_copy);
int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf,
int len, enum mt76x02_eeprom_modes mode)
{
......
......@@ -25,6 +25,7 @@ enum mt76x02_eeprom_field {
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_PCI_ID = 0x00A,
MT_EE_ANTENNA = 0x022,
MT_EE_NIC_CONF_0 = 0x034,
MT_EE_NIC_CONF_1 = 0x036,
MT_EE_COUNTRY_REGION_5GHZ = 0x038,
......@@ -55,6 +56,7 @@ enum mt76x02_eeprom_field {
#define MT_TX_POWER_GROUP_SIZE_5G 5
#define MT_TX_POWER_GROUPS_5G 6
MT_EE_TX_POWER_0_START_5G = 0x062,
MT_EE_TSSI_SLOPE_2G = 0x06e,
MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074,
MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076,
......@@ -85,6 +87,7 @@ enum mt76x02_eeprom_field {
MT_EE_TSSI_BOUND5 = 0x0dc,
MT_EE_TX_POWER_BYRATE_BASE = 0x0de,
MT_EE_TSSI_SLOPE_5G = 0x0f0,
MT_EE_RF_TEMP_COMP_SLOPE_5G = 0x0f2,
MT_EE_RF_TEMP_COMP_SLOPE_2G = 0x0f4,
......@@ -104,6 +107,8 @@ enum mt76x02_eeprom_field {
__MT_EE_MAX
};
#define MT_EE_ANTENNA_DUAL BIT(15)
#define MT_EE_NIC_CONF_0_RX_PATH GENMASK(3, 0)
#define MT_EE_NIC_CONF_0_TX_PATH GENMASK(7, 4)
#define MT_EE_NIC_CONF_0_PA_TYPE GENMASK(9, 8)
......@@ -118,12 +123,9 @@ enum mt76x02_eeprom_field {
#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
#define MT_EE_NIC_CONF_1_TX_ALC_EN BIT(13)
#define MT_EE_NIC_CONF_2_RX_STREAM GENMASK(3, 0)
#define MT_EE_NIC_CONF_2_TX_STREAM GENMASK(7, 4)
#define MT_EE_NIC_CONF_2_HW_ANTDIV BIT(8)
#define MT_EE_NIC_CONF_2_ANT_OPT BIT(3)
#define MT_EE_NIC_CONF_2_ANT_DIV BIT(4)
#define MT_EE_NIC_CONF_2_XTAL_OPTION GENMASK(10, 9)
#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
#define MT_EFUSE_USAGE_MAP_SIZE (MT_EE_USAGE_MAP_END - \
MT_EE_USAGE_MAP_START + 1)
......@@ -188,5 +190,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,
s8 *lna_2g, s8 *lna_5g,
struct ieee80211_channel *chan);
void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev);
int mt76x02_eeprom_copy(struct mt76x02_dev *dev,
enum mt76x02_eeprom_field field,
void *dest, int len);
#endif /* __MT76x02_EEPROM_H */
......@@ -37,18 +37,8 @@ struct mt76x02_tx_status {
#define MT_MAX_VIFS 8
struct mt76x02_vif {
struct mt76_wcid group_wcid; /* must be first */
u8 idx;
struct mt76_wcid group_wcid;
};
struct mt76x02_tx_info {
unsigned long jiffies;
u8 tries;
u8 wcid;
u8 pktid;
u8 retry;
};
DECLARE_EWMA(signal, 10, 8);
......@@ -153,8 +143,6 @@ enum mt76x2_phy_bandwidth {
#define MT_TXWI_ACK_CTL_NSEQ BIT(1)
#define MT_TXWI_ACK_CTL_BA_WINDOW GENMASK(7, 2)
#define MT_TXWI_PKTID_PROBE BIT(7)
struct mt76x02_txwi {
__le16 flags;
__le16 rate;
......@@ -190,18 +178,7 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev)
return false;
}
static inline struct mt76x02_tx_info *
mt76x02_skb_tx_info(struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
return (void *)info->status.status_driver_data;
}
void mt76x02_txq_init(struct mt76x02_dev *dev, struct ieee80211_txq *txq);
enum mt76x02_cipher_type
mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data);
void mt76x02_mac_set_short_preamble(struct mt76x02_dev *dev, bool enable);
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,
......@@ -217,8 +194,7 @@ 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);
int
mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate);
void mt76x02_mac_set_tx_protection(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,
......@@ -226,4 +202,12 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq);
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
struct mt76_queue_entry *e, bool flush);
void mt76x02_update_channel(struct mt76_dev *mdev);
void mt76x02_mac_work(struct work_struct *work);
void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr);
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);
#endif
......@@ -21,7 +21,7 @@
#include "mt76x02_mcu.h"
struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
static struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
{
struct sk_buff *skb;
......@@ -32,7 +32,6 @@ struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
return skb;
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_alloc);
static struct sk_buff *
mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires)
......@@ -80,16 +79,18 @@ mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid,
return 0;
}
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, bool wait_resp)
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int len, bool wait_resp)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
unsigned long expires = jiffies + HZ;
struct sk_buff *skb;
int ret;
u8 seq;
skb = mt76x02_mcu_msg_alloc(data, len);
if (!skb)
return -EINVAL;
return -ENOMEM;
mutex_lock(&mdev->mmio.mcu.mutex);
......@@ -131,11 +132,9 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_send);
int mt76x02_mcu_function_select(struct mt76x02_dev *dev,
enum mcu_function func,
u32 val, bool wait_resp)
int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func,
u32 val)
{
struct sk_buff *skb;
struct {
__le32 id;
__le32 value;
......@@ -143,16 +142,17 @@ int mt76x02_mcu_function_select(struct mt76x02_dev *dev,
.id = cpu_to_le32(func),
.value = cpu_to_le32(val),
};
bool wait = false;
skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
return mt76_mcu_send_msg(dev, skb, CMD_FUN_SET_OP, wait_resp);
if (func != Q_SELECT)
wait = true;
return mt76_mcu_send_msg(dev, CMD_FUN_SET_OP, &msg, sizeof(msg), wait);
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select);
int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on,
bool wait_resp)
int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on)
{
struct sk_buff *skb;
struct {
__le32 mode;
__le32 level;
......@@ -161,15 +161,12 @@ int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on,
.level = cpu_to_le32(0),
};
skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
return mt76_mcu_send_msg(dev, skb, CMD_POWER_SAVING_OP, wait_resp);
return mt76_mcu_send_msg(dev, CMD_POWER_SAVING_OP, &msg, sizeof(msg), false);
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state);
int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type,
u32 param, bool wait)
int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param)
{
struct sk_buff *skb;
struct {
__le32 id;
__le32 value;
......@@ -177,17 +174,18 @@ int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type,
.id = cpu_to_le32(type),
.value = cpu_to_le32(param),
};
bool is_mt76x2e = mt76_is_mmio(dev) && is_mt76x2(dev);
int ret;
if (wait)
if (is_mt76x2e)
mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0);
skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg));
ret = mt76_mcu_send_msg(dev, skb, CMD_CALIBRATION_OP, true);
ret = mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg),
true);
if (ret)
return ret;
if (wait &&
if (is_mt76x2e &&
WARN_ON(!mt76_poll_msec(dev, MT_MCU_COM_REG0,
BIT(31), BIT(31), 100)))
return -ETIMEDOUT;
......
......@@ -97,16 +97,12 @@ struct mt76x02_patch_header {
};
int mt76x02_mcu_cleanup(struct mt76x02_dev *dev);
int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type,
u32 param, bool wait);
struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len);
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, bool wait_resp);
int mt76x02_mcu_function_select(struct mt76x02_dev *dev,
enum mcu_function func,
u32 val, bool wait_resp);
int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on,
bool wait_resp);
int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param);
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int len, bool wait_resp);
int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func,
u32 val);
int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on);
void mt76x02_set_ethtool_fwver(struct mt76x02_dev *dev,
const struct mt76x02_fw_header *h);
......
......@@ -254,5 +254,6 @@ void mt76x02_init_agc_gain(struct mt76x02_dev *dev)
memcpy(dev->cal.agc_gain_cur, dev->cal.agc_gain_init,
sizeof(dev->cal.agc_gain_cur));
dev->cal.low_gain = -1;
dev->cal.gain_init_done = true;
}
EXPORT_SYMBOL_GPL(mt76x02_init_agc_gain);
......@@ -3,11 +3,11 @@ obj-$(CONFIG_MT76x2E) += mt76x2e.o
obj-$(CONFIG_MT76x2U) += mt76x2u.o
mt76x2-common-y := \
eeprom.o mac.o init.o phy.o debugfs.o mcu.o
eeprom.o mac.o init.o phy.o mcu.o
mt76x2e-y := \
pci.o pci_main.o pci_init.o pci_tx.o \
pci_mac.o pci_mcu.o pci_phy.o pci_dfs.o
pci.o pci_main.o pci_init.o pci_mcu.o \
pci_phy.o
mt76x2u-y := \
usb.o usb_init.o usb_main.o usb_mac.o usb_mcu.o \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -131,8 +131,8 @@ static int __maybe_unused mt76x2u_resume(struct usb_interface *intf)
}
MODULE_DEVICE_TABLE(usb, mt76x2u_device_table);
MODULE_FIRMWARE(MT7662U_FIRMWARE);
MODULE_FIRMWARE(MT7662U_ROM_PATCH);
MODULE_FIRMWARE(MT7662_FIRMWARE);
MODULE_FIRMWARE(MT7662_ROM_PATCH);
static struct usb_driver mt76x2u_driver = {
.name = KBUILD_MODNAME,
......
This diff is collapsed.
This diff is collapsed.
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