summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-04 00:04:18 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-04 00:04:18 +0300
commit5bb053bef82523a8fd78d650bca81c9f114fa276 (patch)
tree58c2fe47f60bb69230bb05d57a6c9e3f47f7b1fe /drivers/net/wireless/mediatek
parentbb2407a7219760926760f0448fddf00d625e5aec (diff)
parent159f02977b2feb18a4bece5e586c838a6d26d44b (diff)
downloadlinux-5bb053bef82523a8fd78d650bca81c9f114fa276.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Support offloading wireless authentication to userspace via NL80211_CMD_EXTERNAL_AUTH, from Srinivas Dasari. 2) A lot of work on network namespace setup/teardown from Kirill Tkhai. Setup and cleanup of namespaces now all run asynchronously and thus performance is significantly increased. 3) Add rx/tx timestamping support to mv88e6xxx driver, from Brandon Streiff. 4) Support zerocopy on RDS sockets, from Sowmini Varadhan. 5) Use denser instruction encoding in x86 eBPF JIT, from Daniel Borkmann. 6) Support hw offload of vlan filtering in mvpp2 dreiver, from Maxime Chevallier. 7) Support grafting of child qdiscs in mlxsw driver, from Nogah Frankel. 8) Add packet forwarding tests to selftests, from Ido Schimmel. 9) Deal with sub-optimal GSO packets better in BBR congestion control, from Eric Dumazet. 10) Support 5-tuple hashing in ipv6 multipath routing, from David Ahern. 11) Add path MTU tests to selftests, from Stefano Brivio. 12) Various bits of IPSEC offloading support for mlx5, from Aviad Yehezkel, Yossi Kuperman, and Saeed Mahameed. 13) Support RSS spreading on ntuple filters in SFC driver, from Edward Cree. 14) Lots of sockmap work from John Fastabend. Applications can use eBPF to filter sendmsg and sendpage operations. 15) In-kernel receive TLS support, from Dave Watson. 16) Add XDP support to ixgbevf, this is significant because it should allow optimized XDP usage in various cloud environments. From Tony Nguyen. 17) Add new Intel E800 series "ice" ethernet driver, from Anirudh Venkataramanan et al. 18) IP fragmentation match offload support in nfp driver, from Pieter Jansen van Vuuren. 19) Support XDP redirect in i40e driver, from Björn Töpel. 20) Add BPF_RAW_TRACEPOINT program type for accessing the arguments of tracepoints in their raw form, from Alexei Starovoitov. 21) Lots of striding RQ improvements to mlx5 driver with many performance improvements, from Tariq Toukan. 22) Use rhashtable for inet frag reassembly, from Eric Dumazet. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1678 commits) net: mvneta: improve suspend/resume net: mvneta: split rxq/txq init and txq deinit into SW and HW parts ipv6: frags: fix /proc/sys/net/ipv6/ip6frag_low_thresh net: bgmac: Fix endian access in bgmac_dma_tx_ring_free() net: bgmac: Correctly annotate register space route: check sysctl_fib_multipath_use_neigh earlier than hash fix typo in command value in drivers/net/phy/mdio-bitbang. sky2: Increase D3 delay to sky2 stops working after suspend net/mlx5e: Set EQE based as default TX interrupt moderation mode ibmvnic: Disable irqs before exiting reset from closed state net: sched: do not emit messages while holding spinlock vlan: also check phy_driver ts_info for vlan's real device Bluetooth: Mark expected switch fall-throughs Bluetooth: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for BTUSB_QCA_ROME Bluetooth: btrsi: remove unused including <linux/version.h> Bluetooth: hci_bcm: Remove DMI quirk for the MINIX Z83-4 sh_eth: kill useless check in __sh_eth_get_regs() sh_eth: add sh_eth_cpu_data::no_xdfar flag ipv6: factorize sk_wmem_alloc updates done by __ip6_append_data() ipv4: factorize sk_wmem_alloc updates done by __ip_append_data() ...
Diffstat (limited to 'drivers/net/wireless/mediatek')
-rw-r--r--drivers/net/wireless/mediatek/Kconfig4
-rw-r--r--drivers/net/wireless/mediatek/mt76/debugfs.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c68
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c12
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_init.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mac.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_main.c47
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_phy.c55
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_regs.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_tx.c5
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/debugfs.c16
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/eeprom.c26
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/initvals.h1
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/mac.c26
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/mac.h1
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/main.c3
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/mcu.c7
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/mt7601u.h3
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/trace.h6
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/usb.c52
24 files changed, 256 insertions, 120 deletions
diff --git a/drivers/net/wireless/mediatek/Kconfig b/drivers/net/wireless/mediatek/Kconfig
index 92ce4062f307..ff5fc8987b0a 100644
--- a/drivers/net/wireless/mediatek/Kconfig
+++ b/drivers/net/wireless/mediatek/Kconfig
@@ -5,8 +5,8 @@ config WLAN_VENDOR_MEDIATEK
If you have a wireless card belonging to this class, say Y.
Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about cards. If you say Y, you will be asked for
+ kernel: saying N will just cause the configurator to skip all the
+ questions about these cards. If you say Y, you will be asked for
your specific card in the following questions.
if WLAN_VENDOR_MEDIATEK
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c
index c121b502a462..a38d05dea599 100644
--- a/drivers/net/wireless/mediatek/mt76/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/debugfs.c
@@ -64,13 +64,13 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
if (!dir)
return NULL;
- debugfs_create_u8("led_pin", S_IRUSR | S_IWUSR, dir, &dev->led_pin);
- debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
- debugfs_create_file_unsafe("regval", S_IRUSR | S_IWUSR, dir, dev,
+ debugfs_create_u8("led_pin", 0600, dir, &dev->led_pin);
+ debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg);
+ debugfs_create_file_unsafe("regval", 0600, dir, dev,
&fops_regval);
- debugfs_create_blob("eeprom", S_IRUSR, dir, &dev->eeprom);
+ debugfs_create_blob("eeprom", 0400, dir, &dev->eeprom);
if (dev->otp.data)
- debugfs_create_blob("otp", S_IRUSR, dir, &dev->otp);
+ debugfs_create_blob("otp", 0400, dir, &dev->otp);
debugfs_create_devm_seqfile(dev->dev, "queues", dir, mt76_queues_read);
return dir;
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 85f8d324ebf8..4f30cdcd2b53 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -119,6 +119,52 @@ static int mt76_led_init(struct mt76_dev *dev)
return devm_led_classdev_register(dev->dev, &dev->led_cdev);
}
+static void mt76_init_stream_cap(struct mt76_dev *dev,
+ struct ieee80211_supported_band *sband,
+ bool vht)
+{
+ struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
+ int i, nstream = __sw_hweight8(dev->antenna_mask);
+ struct ieee80211_sta_vht_cap *vht_cap;
+ u16 mcs_map = 0;
+
+ if (nstream > 1)
+ ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC;
+ else
+ ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC;
+
+ for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
+ ht_cap->mcs.rx_mask[i] = i < nstream ? 0xff : 0;
+
+ if (!vht)
+ return;
+
+ vht_cap = &sband->vht_cap;
+ if (nstream > 1)
+ vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
+ else
+ vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC;
+
+ for (i = 0; i < 8; i++) {
+ if (i < nstream)
+ mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2));
+ else
+ mcs_map |=
+ (IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2));
+ }
+ vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+ vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+}
+
+void mt76_set_stream_caps(struct mt76_dev *dev, bool vht)
+{
+ if (dev->cap.has_2ghz)
+ mt76_init_stream_cap(dev, &dev->sband_2g.sband, false);
+ if (dev->cap.has_5ghz)
+ mt76_init_stream_cap(dev, &dev->sband_5g.sband, vht);
+}
+EXPORT_SYMBOL_GPL(mt76_set_stream_caps);
+
static int
mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
const struct ieee80211_channel *chan, int n_chan,
@@ -128,7 +174,6 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
void *chanlist;
- u16 mcs_map;
int size;
size = n_chan * sizeof(*chan);
@@ -153,34 +198,20 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_TX_STBC |
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
- ht_cap->mcs.rx_mask[0] = 0xff;
- ht_cap->mcs.rx_mask[1] = 0xff;
ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
+ mt76_init_stream_cap(dev, sband, vht);
+
if (!vht)
return 0;
vht_cap = &sband->vht_cap;
vht_cap->vht_supported = true;
-
- mcs_map = (IEEE80211_VHT_MCS_SUPPORT_0_9 << (0 * 2)) |
- (IEEE80211_VHT_MCS_SUPPORT_0_9 << (1 * 2)) |
- (IEEE80211_VHT_MCS_NOT_SUPPORTED << (2 * 2)) |
- (IEEE80211_VHT_MCS_NOT_SUPPORTED << (3 * 2)) |
- (IEEE80211_VHT_MCS_NOT_SUPPORTED << (4 * 2)) |
- (IEEE80211_VHT_MCS_NOT_SUPPORTED << (5 * 2)) |
- (IEEE80211_VHT_MCS_NOT_SUPPORTED << (6 * 2)) |
- (IEEE80211_VHT_MCS_NOT_SUPPORTED << (7 * 2));
-
- vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
- vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC |
- IEEE80211_VHT_CAP_TXSTBC |
IEEE80211_VHT_CAP_RXSTBC_1 |
IEEE80211_VHT_CAP_SHORT_GI_80;
@@ -262,6 +293,9 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
+ wiphy->available_antennas_tx = dev->antenna_mask;
+ wiphy->available_antennas_rx = dev->antenna_mask;
+
hw->txq_data_size = sizeof(struct mt76_txq);
hw->max_tx_fragments = 16;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index d2ce15093edd..065ff78059c3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -253,6 +253,8 @@ struct mt76_dev {
u32 rev;
unsigned long state;
+ u8 antenna_mask;
+
struct mt76_sband sband_2g;
struct mt76_sband sband_5g;
struct debugfs_blob_wrapper eeprom;
@@ -423,6 +425,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw,
void mt76_set_channel(struct mt76_dev *dev);
int mt76_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
+void mt76_set_stream_caps(struct mt76_dev *dev, bool vht);
int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid,
u16 ssn, u8 size);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2.h
index e62131b88102..783b8122ec3c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2.h
@@ -180,6 +180,7 @@ int mt76x2_eeprom_init(struct mt76x2_dev *dev);
int mt76x2_apply_calibration_data(struct mt76x2_dev *dev, int channel);
void mt76x2_set_tx_ackto(struct mt76x2_dev *dev);
+void mt76x2_phy_set_antenna(struct mt76x2_dev *dev);
int mt76x2_phy_start(struct mt76x2_dev *dev);
int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
struct cfg80211_chan_def *chandef);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c
index 612feb593d7d..955ea3e692dd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c
@@ -123,11 +123,11 @@ void mt76x2_init_debugfs(struct mt76x2_dev *dev)
if (!dir)
return;
- debugfs_create_u8("temperature", S_IRUSR, dir, &dev->cal.temp);
- debugfs_create_bool("tpc", S_IRUSR | S_IWUSR, dir, &dev->enable_tpc);
+ debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp);
+ debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc);
- debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
- debugfs_create_file("dfs_stats", S_IRUSR, dir, dev, &fops_dfs_stat);
+ debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
+ debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat);
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir,
read_txpower);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
index 9c9bf3e785ba..5bb50027c1e8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c
@@ -222,11 +222,10 @@ static int
mt76x2_eeprom_load(struct mt76x2_dev *dev)
{
void *efuse;
- int len = MT7662_EEPROM_SIZE;
bool found;
int ret;
- ret = mt76_eeprom_init(&dev->mt76, len);
+ ret = mt76_eeprom_init(&dev->mt76, MT7662_EEPROM_SIZE);
if (ret < 0)
return ret;
@@ -234,14 +233,15 @@ mt76x2_eeprom_load(struct mt76x2_dev *dev)
if (found)
found = !mt76x2_check_eeprom(dev);
- dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
- dev->mt76.otp.size = len;
+ dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, MT7662_EEPROM_SIZE,
+ GFP_KERNEL);
+ dev->mt76.otp.size = MT7662_EEPROM_SIZE;
if (!dev->mt76.otp.data)
return -ENOMEM;
efuse = dev->mt76.otp.data;
- if (mt76x2_get_efuse_data(dev, efuse, len))
+ if (mt76x2_get_efuse_data(dev, efuse, MT7662_EEPROM_SIZE))
goto out;
if (found) {
@@ -249,7 +249,7 @@ mt76x2_eeprom_load(struct mt76x2_dev *dev)
} else {
/* FIXME: check if efuse data is complete */
found = true;
- memcpy(dev->mt76.eeprom.data, efuse, len);
+ memcpy(dev->mt76.eeprom.data, efuse, MT7662_EEPROM_SIZE);
}
out:
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
index 9dbf94947324..934c331d995e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
@@ -857,6 +857,9 @@ int mt76x2_register_device(struct mt76x2_dev *dev)
dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
+ /* init antenna configuration */
+ dev->mt76.antenna_mask = 3;
+
ret = mt76_register_device(&dev->mt76, true, mt76x2_rates,
ARRAY_SIZE(mt76x2_rates));
if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
index 7ea3d841918e..d18315652583 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
@@ -198,8 +198,8 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
ccmp_pn[5] = pn >> 24;
ccmp_pn[6] = pn >> 32;
ccmp_pn[7] = pn >> 40;
- txwi->iv = *((u32 *) &ccmp_pn[0]);
- txwi->eiv = *((u32 *) &ccmp_pn[1]);
+ txwi->iv = *((__le32 *)&ccmp_pn[0]);
+ txwi->eiv = *((__le32 *)&ccmp_pn[1]);
}
spin_lock_bh(&dev->mt76.lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
index 205043b470b2..73c127f92613 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
@@ -336,6 +336,17 @@ mt76x2_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
int idx = key->keyidx;
int ret;
+ /* fall back to sw encryption for unsupported ciphers */
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ case WLAN_CIPHER_SUITE_CCMP:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
/*
* The hardware does not support per-STA RX GTK, fall back
* to software mode for these.
@@ -549,6 +560,40 @@ mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
return 0;
}
+static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
+ u32 rx_ant)
+{
+ struct mt76x2_dev *dev = hw->priv;
+
+ if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant)
+ return -EINVAL;
+
+ mutex_lock(&dev->mutex);
+
+ dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101;
+ dev->mt76.antenna_mask = tx_ant;
+
+ mt76_set_stream_caps(&dev->mt76, true);
+ mt76x2_phy_set_antenna(dev);
+
+ mutex_unlock(&dev->mutex);
+
+ return 0;
+}
+
+static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
+ u32 *rx_ant)
+{
+ struct mt76x2_dev *dev = hw->priv;
+
+ mutex_lock(&dev->mutex);
+ *tx_ant = dev->mt76.antenna_mask;
+ *rx_ant = dev->mt76.antenna_mask;
+ mutex_unlock(&dev->mutex);
+
+ return 0;
+}
+
const struct ieee80211_ops mt76x2_ops = {
.tx = mt76x2_tx,
.start = mt76x2_start,
@@ -573,5 +618,7 @@ const struct ieee80211_ops mt76x2_ops = {
.set_coverage_class = mt76x2_set_coverage_class,
.get_survey = mt76_get_survey,
.set_tim = mt76x2_set_tim,
+ .set_antenna = mt76x2_set_antenna,
+ .get_antenna = mt76x2_get_antenna,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
index 15820b11f9db..dfd36d736b06 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c
@@ -187,7 +187,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev)
{
const struct firmware *fw;
const struct mt76x2_fw_header *hdr;
- int i, len, ret;
+ int len, ret;
__le32 *cur;
u32 offset, val;
@@ -240,16 +240,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev)
/* trigger firmware */
mt76_wr(dev, MT_MCU_INT_LEVEL, 2);
- for (i = 200; i > 0; i--) {
- val = mt76_rr(dev, MT_MCU_COM_REG0);
-
- if (val & 1)
- break;
-
- msleep(10);
- }
-
- if (!i) {
+ if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 200)) {
dev_err(dev->mt76.dev, "Firmware failed to start\n");
release_firmware(fw);
return -ETIMEDOUT;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
index 5b742749d5de..fcc37eb7ce0b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c
@@ -361,30 +361,53 @@ mt76x2_phy_set_band(struct mt76x2_dev *dev, int band, bool primary_upper)
primary_upper);
}
-static void
-mt76x2_set_rx_chains(struct mt76x2_dev *dev)
+void mt76x2_phy_set_antenna(struct mt76x2_dev *dev)
{
u32 val;
val = mt76_rr(dev, MT_BBP(AGC, 0));
- val &= ~(BIT(3) | BIT(4));
+ val &= ~(BIT(4) | BIT(1));
+ switch (dev->mt76.antenna_mask) {
+ case 1:
+ /* disable mac DAC control */
+ mt76_clear(dev, MT_BBP(IBI, 9), BIT(11));
+ mt76_clear(dev, MT_BBP(TXBE, 5), 3);
+ mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0x3);
+ mt76_rmw_field(dev, MT_BBP(CORE, 32), GENMASK(21, 20), 2);
+ /* disable DAC 1 */
+ mt76_rmw_field(dev, MT_BBP(CORE, 33), GENMASK(12, 9), 4);
- if (dev->chainmask & BIT(1))
- val |= BIT(3);
+ val &= ~(BIT(3) | BIT(0));
+ break;
+ case 2:
+ /* disable mac DAC control */
+ mt76_clear(dev, MT_BBP(IBI, 9), BIT(11));
+ mt76_rmw_field(dev, MT_BBP(TXBE, 5), 3, 1);
+ mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0xc);
+ mt76_rmw_field(dev, MT_BBP(CORE, 32), GENMASK(21, 20), 1);
+ /* disable DAC 0 */
+ mt76_rmw_field(dev, MT_BBP(CORE, 33), GENMASK(12, 9), 1);
+
+ val &= ~BIT(3);
+ val |= BIT(0);
+ break;
+ case 3:
+ default:
+ /* enable mac DAC control */
+ mt76_set(dev, MT_BBP(IBI, 9), BIT(11));
+ mt76_set(dev, MT_BBP(TXBE, 5), 3);
+ mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0xf);
+ mt76_clear(dev, MT_BBP(CORE, 32), GENMASK(21, 20));
+ mt76_clear(dev, MT_BBP(CORE, 33), GENMASK(12, 9));
+ val &= ~BIT(0);
+ val |= BIT(3);
+ break;
+ }
mt76_wr(dev, MT_BBP(AGC, 0), val);
}
static void
-mt76x2_set_tx_dac(struct mt76x2_dev *dev)
-{
- if (dev->chainmask & BIT(1))
- mt76_set(dev, MT_BBP(TXBE, 5), 3);
- else
- mt76_clear(dev, MT_BBP(TXBE, 5), 3);
-}
-
-static void
mt76x2_get_agc_gain(struct mt76x2_dev *dev, u8 *dest)
{
dest[0] = mt76_get_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN);
@@ -585,10 +608,8 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
mt76x2_configure_tx_delay(dev, band, bw);
mt76x2_phy_set_txpower(dev);
- mt76x2_set_rx_chains(dev);
mt76x2_phy_set_band(dev, chan->band, ch_group_index & 1);
mt76x2_phy_set_bw(dev, chandef->width, ch_group_index);
- mt76x2_set_tx_dac(dev);
mt76_rmw(dev, MT_EXT_CCA_CFG,
(MT_EXT_CCA_CFG_CCA0 |
@@ -604,6 +625,8 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
mt76x2_mcu_init_gain(dev, channel, dev->cal.rx.mcu_gain, true);
+ mt76x2_phy_set_antenna(dev);
+
/* Enable LDPC Rx */
if (mt76xx_rev(dev) >= MT76XX_REV_E3)
mt76_set(dev, MT_BBP(RXO, 13), BIT(10));
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x2_regs.h
index ce3ab85c8b0f..b9c334d9e5b8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_regs.h
@@ -321,6 +321,8 @@
#define MT_TX_PWR_CFG_2 0x131c
#define MT_TX_PWR_CFG_3 0x1320
#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_BAND_CFG 0x132c
#define MT_TX_BAND_CFG_UPPER_40M BIT(0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
index 534e4bf9a34c..e46eafc4c436 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
@@ -36,9 +36,12 @@ void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
msta = (struct mt76x2_sta *) control->sta->drv_priv;
wcid = &msta->wcid;
+ /* sw encrypted frames */
+ if (!info->control.hw_key && wcid->hw_key_idx != -1)
+ control->sta = NULL;
}
- if (vif || (!info->control.hw_key && wcid->hw_key_idx != -1)) {
+ if (vif && !control->sta) {
struct mt76x2_vif *mvif;
mvif = (struct mt76x2_vif *) vif->drv_priv;
diff --git a/drivers/net/wireless/mediatek/mt7601u/debugfs.c b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
index fc008475a03b..991a6a729b1e 100644
--- a/drivers/net/wireless/mediatek/mt7601u/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
@@ -160,13 +160,11 @@ void mt7601u_init_debugfs(struct mt7601u_dev *dev)
if (!dir)
return;
- debugfs_create_u8("temperature", S_IRUSR, dir, &dev->raw_temp);
- debugfs_create_u32("temp_mode", S_IRUSR, dir, &dev->temp_mode);
-
- debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
- debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
- &fops_regval);
- debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
- debugfs_create_file("eeprom_param", S_IRUSR, dir, dev,
- &fops_eeprom_param);
+ debugfs_create_u8("temperature", 0400, dir, &dev->raw_temp);
+ debugfs_create_u32("temp_mode", 0400, dir, &dev->temp_mode);
+
+ debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg);
+ debugfs_create_file("regval", 0600, dir, dev, &fops_regval);
+ debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
+ debugfs_create_file("eeprom_param", 0400, dir, dev, &fops_eeprom_param);
}
diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.c b/drivers/net/wireless/mediatek/mt7601u/eeprom.c
index da6faea092d6..76117b402880 100644
--- a/drivers/net/wireless/mediatek/mt7601u/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt7601u/eeprom.c
@@ -19,6 +19,7 @@
#include <asm/unaligned.h>
#include "mt7601u.h"
#include "eeprom.h"
+#include "mac.h"
static bool
field_valid(u8 val)
@@ -74,7 +75,7 @@ static int
mt7601u_efuse_physical_size_check(struct mt7601u_dev *dev)
{
const int map_reads = DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16);
- u8 data[map_reads * 16];
+ u8 data[round_up(MT_EFUSE_USAGE_MAP_SIZE, 16)];
int ret, i;
u32 start = 0, end = 0, cnt_free;
@@ -134,27 +135,6 @@ mt7601u_set_chip_cap(struct mt7601u_dev *dev, u8 *eeprom)
"Error: device has more than 1 RX/TX stream!\n");
}
-static int
-mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *eeprom)
-{
- const void *src = eeprom + MT_EE_MAC_ADDR;
-
- ether_addr_copy(dev->macaddr, src);
-
- if (!is_valid_ether_addr(dev->macaddr)) {
- eth_random_addr(dev->macaddr);
- dev_info(dev->dev,
- "Invalid MAC address, using random address %pM\n",
- dev->macaddr);
- }
-
- mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
- mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) |
- FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
-
- return 0;
-}
-
static void mt7601u_set_channel_target_power(struct mt7601u_dev *dev,
u8 *eeprom, u8 max_pwr)
{
@@ -400,7 +380,7 @@ mt7601u_eeprom_init(struct mt7601u_dev *dev)
dev_info(dev->dev, "EEPROM ver:%02hhx fae:%02hhx\n",
eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]);
- mt7601u_set_macaddr(dev, eeprom);
+ mt7601u_set_macaddr(dev, eeprom + MT_EE_MAC_ADDR);
mt7601u_set_chip_cap(dev, eeprom);
mt7601u_set_channel_power(dev, eeprom);
mt7601u_set_country_reg(dev, eeprom);
diff --git a/drivers/net/wireless/mediatek/mt7601u/initvals.h b/drivers/net/wireless/mediatek/mt7601u/initvals.h
index ec11ff66969d..2dc6b68e7fb9 100644
--- a/drivers/net/wireless/mediatek/mt7601u/initvals.h
+++ b/drivers/net/wireless/mediatek/mt7601u/initvals.h
@@ -139,6 +139,7 @@ static const struct mt76_reg_pair mac_common_vals[] = {
{ MT_TXOP_HLDR_ET, 0x00000002 },
{ MT_XIFS_TIME_CFG, 0x33a41010 },
{ MT_PWR_PIN_CFG, 0x00000000 },
+ { MT_PN_PAD_MODE, 0x00000001 },
};
static const struct mt76_reg_pair mac_chip_vals[] = {
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c
index d6dc59bb00df..d55d7040a56d 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mac.c
+++ b/drivers/net/wireless/mediatek/mt7601u/mac.c
@@ -16,6 +16,22 @@
#include "trace.h"
#include <linux/etherdevice.h>
+void mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *addr)
+{
+ ether_addr_copy(dev->macaddr, addr);
+
+ if (!is_valid_ether_addr(dev->macaddr)) {
+ eth_random_addr(dev->macaddr);
+ dev_info(dev->dev,
+ "Invalid MAC address, using random address %pM\n",
+ dev->macaddr);
+ }
+
+ mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
+ mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) |
+ FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
+}
+
static void
mt76_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate)
{
@@ -464,8 +480,16 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
status->flag |= RX_FLAG_DECRYPTED;
- status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
+ status->flag |= RX_FLAG_MMIC_STRIPPED;
+ status->flag |= RX_FLAG_MIC_STRIPPED;
+ status->flag |= RX_FLAG_ICV_STRIPPED;
+ status->flag |= RX_FLAG_IV_STRIPPED;
}
+ /* let mac80211 take care of PN validation since apparently
+ * the hardware does not support it
+ */
+ if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_PN_LEN))
+ status->flag &= ~RX_FLAG_IV_STRIPPED;
status->chains = BIT(0);
rssi = mt7601u_phy_get_rssi(dev, rxwi, rate);
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.h b/drivers/net/wireless/mediatek/mt7601u/mac.h
index 2c22d63c63a2..b7aa24656d0e 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mac.h
+++ b/drivers/net/wireless/mediatek/mt7601u/mac.h
@@ -174,5 +174,6 @@ u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev,
struct mt76_tx_status
mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev);
void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat);
+void mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *addr);
#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index 43ebd460ba86..3c9ea40d9584 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -64,6 +64,9 @@ static int mt7601u_add_interface(struct ieee80211_hw *hw,
*/
mvif->idx = idx;
+ if (!ether_addr_equal(dev->macaddr, vif->addr))
+ mt7601u_set_macaddr(dev, vif->addr);
+
if (dev->wcid_mask[wcid / BITS_PER_LONG] & BIT(wcid % BITS_PER_LONG))
return -ENOSPC;
dev->wcid_mask[wcid / BITS_PER_LONG] |= BIT(wcid % BITS_PER_LONG);
diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.c b/drivers/net/wireless/mediatek/mt7601u/mcu.c
index 65a8004418ea..d9d6fd7eff5e 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mcu.c
+++ b/drivers/net/wireless/mediatek/mt7601u/mcu.c
@@ -58,8 +58,7 @@ static inline void trace_mt_mcu_msg_send_cs(struct mt7601u_dev *dev,
trace_mt_mcu_msg_send(dev, skb, csum, need_resp);
}
-static struct sk_buff *
-mt7601u_mcu_msg_alloc(struct mt7601u_dev *dev, const void *data, int len)
+static struct sk_buff *mt7601u_mcu_msg_alloc(const void *data, int len)
{
struct sk_buff *skb;
@@ -171,7 +170,7 @@ static int mt7601u_mcu_function_select(struct mt7601u_dev *dev,
.value = cpu_to_le32(val),
};
- skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
+ skb = mt7601u_mcu_msg_alloc(&msg, sizeof(msg));
if (!skb)
return -ENOMEM;
return mt7601u_mcu_msg_send(dev, skb, CMD_FUN_SET_OP, func == 5);
@@ -208,7 +207,7 @@ mt7601u_mcu_calibrate(struct mt7601u_dev *dev, enum mcu_calibrate cal, u32 val)
.value = cpu_to_le32(val),
};
- skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
+ skb = mt7601u_mcu_msg_alloc(&msg, sizeof(msg));
if (!skb)
return -ENOMEM;
return mt7601u_mcu_msg_send(dev, skb, CMD_CALIBRATION_OP, true);
diff --git a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
index c7ec40475a5f..9233744451a9 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
+++ b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
@@ -147,7 +147,8 @@ enum {
* @rx_lock: protects @rx_q.
* @con_mon_lock: protects @ap_bssid, @bcn_*, @avg_rssi.
* @mutex: ensures exclusive access from mac80211 callbacks.
- * @vendor_req_mutex: protects @vend_buf, ensures atomicity of split writes.
+ * @vendor_req_mutex: protects @vend_buf, ensures atomicity of read/write
+ * accesses
* @reg_atomic_mutex: ensures atomicity of indirect register accesses
* (accesses to RF and BBP).
* @hw_atomic_mutex: ensures exclusive access to HW during critical
diff --git a/drivers/net/wireless/mediatek/mt7601u/trace.h b/drivers/net/wireless/mediatek/mt7601u/trace.h
index 289897300ef0..82c8898b9076 100644
--- a/drivers/net/wireless/mediatek/mt7601u/trace.h
+++ b/drivers/net/wireless/mediatek/mt7601u/trace.h
@@ -34,7 +34,7 @@
#define REG_PR_FMT "%04x=%08x"
#define REG_PR_ARG __entry->reg, __entry->val
-DECLARE_EVENT_CLASS(dev_reg_evt,
+DECLARE_EVENT_CLASS(dev_reg_evtu,
TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
TP_ARGS(dev, reg, val),
TP_STRUCT__entry(
@@ -51,12 +51,12 @@ DECLARE_EVENT_CLASS(dev_reg_evt,
)
);
-DEFINE_EVENT(dev_reg_evt, reg_read,
+DEFINE_EVENT(dev_reg_evtu, reg_read,
TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
TP_ARGS(dev, reg, val)
);
-DEFINE_EVENT(dev_reg_evt, reg_write,
+DEFINE_EVENT(dev_reg_evtu, reg_write,
TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
TP_ARGS(dev, reg, val)
);
diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c
index b9e4f6793138..d8b7863f7926 100644
--- a/drivers/net/wireless/mediatek/mt7601u/usb.c
+++ b/drivers/net/wireless/mediatek/mt7601u/usb.c
@@ -129,15 +129,14 @@ void mt7601u_vendor_reset(struct mt7601u_dev *dev)
MT_VEND_DEV_MODE_RESET, 0, NULL, 0);
}
-u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
+/* should be called with vendor_req_mutex held */
+static u32 __mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
{
int ret;
u32 val = ~0;
WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset);
- mutex_lock(&dev->vendor_req_mutex);
-
ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN,
0, offset, dev->vend_buf, MT_VEND_BUF);
if (ret == MT_VEND_BUF)
@@ -146,25 +145,41 @@ u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n",
ret, offset);
- mutex_unlock(&dev->vendor_req_mutex);
-
trace_reg_read(dev, offset, val);
return val;
}
-int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
- const u16 offset, const u32 val)
+u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
{
- int ret;
+ u32 ret;
mutex_lock(&dev->vendor_req_mutex);
+ ret = __mt7601u_rr(dev, offset);
+ mutex_unlock(&dev->vendor_req_mutex);
- ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
- val & 0xffff, offset, NULL, 0);
+ return ret;
+}
+
+/* should be called with vendor_req_mutex held */
+static int __mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
+ const u16 offset, const u32 val)
+{
+ int ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
+ val & 0xffff, offset, NULL, 0);
if (!ret)
ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
val >> 16, offset + 2, NULL, 0);
+ trace_reg_write(dev, offset, val);
+ return ret;
+}
+
+int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
+ const u16 offset, const u32 val)
+{
+ int ret;
+ mutex_lock(&dev->vendor_req_mutex);
+ ret = __mt7601u_vendor_single_wr(dev, req, offset, val);
mutex_unlock(&dev->vendor_req_mutex);
return ret;
@@ -175,23 +190,30 @@ void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
WARN_ONCE(offset > USHRT_MAX, "write high off:%08x", offset);
mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
- trace_reg_write(dev, offset, val);
}
u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
{
- val |= mt7601u_rr(dev, offset) & ~mask;
- mt7601u_wr(dev, offset, val);
+ mutex_lock(&dev->vendor_req_mutex);
+ val |= __mt7601u_rr(dev, offset) & ~mask;
+ __mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
+ mutex_unlock(&dev->vendor_req_mutex);
+
return val;
}
u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
{
- u32 reg = mt7601u_rr(dev, offset);
+ u32 reg;
+ mutex_lock(&dev->vendor_req_mutex);
+ reg = __mt7601u_rr(dev, offset);
val |= reg & ~mask;
if (reg != val)
- mt7601u_wr(dev, offset, val);
+ __mt7601u_vendor_single_wr(dev, MT_VEND_WRITE,
+ offset, val);
+ mutex_unlock(&dev->vendor_req_mutex);
+
return val;
}