mt76 patches for 5.13
* code cleanup * mt7915/mt7615 decap offload support * driver fixes * mt7613 eeprom support * MCU code unification * threaded NAPI support * new device IDs * mt7921 device reset support * rx timestamp support -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iEYEABECAAYFAmB0t30ACgkQ130UHQKnbvUn1gCfVybGmVsXGEZy05Zci0nzqu58 TFMAoItsQM6BieJvGMifoQov1ogTaTc9 =xjS9 -----END PGP SIGNATURE----- Merge tag 'mt76-for-kvalo-2021-04-12' of https://github.com/nbd168/wireless mt76 patches for 5.13 * code cleanup * mt7915/mt7615 decap offload support * driver fixes * mt7613 eeprom support * MCU code unification * threaded NAPI support * new device IDs * mt7921 device reset support * rx timestamp support # gpg: Signature made Tue 13 Apr 2021 12:11:25 AM EEST using DSA key ID 02A76EF5 # gpg: Good signature from "Felix Fietkau <nbd@nbd.name>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 75D1 1A7D 91A7 710F 4900 42EF D77D 141D 02A7 6EF5
This commit is contained in:
commit
961b27ffc5
@ -1,24 +0,0 @@
|
||||
Common IEEE 802.11 properties
|
||||
|
||||
This provides documentation of common properties that are valid for all wireless
|
||||
devices.
|
||||
|
||||
Optional properties:
|
||||
- ieee80211-freq-limit : list of supported frequency ranges in KHz. This can be
|
||||
used for devices that in a given config support less channels than
|
||||
normally. It may happen chipset supports a wide wireless band but it is
|
||||
limited to some part of it due to used antennas or power amplifier.
|
||||
An example case for this can be tri-band wireless router with two
|
||||
identical chipsets used for two different 5 GHz subbands. Using them
|
||||
incorrectly could not work or decrease performance noticeably.
|
||||
|
||||
Example:
|
||||
|
||||
pcie@0,0 {
|
||||
reg = <0x0000 0 0 0 0>;
|
||||
wifi@0,0 {
|
||||
reg = <0x0000 0 0 0 0>;
|
||||
ieee80211-freq-limit = <2402000 2482000>,
|
||||
<5170000 5250000>;
|
||||
};
|
||||
};
|
@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/ieee80211.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common IEEE 802.11 Binding
|
||||
|
||||
maintainers:
|
||||
- Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
|
||||
description: |
|
||||
This provides documentation of common properties that are valid for
|
||||
all wireless devices
|
||||
|
||||
properties:
|
||||
ieee80211-freq-limit:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-matrix
|
||||
items:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
description:
|
||||
List of supported frequency ranges in KHz. This can be used for devices
|
||||
that in a given config support less channels than normally. It may happen
|
||||
chipset supports a wide wireless band but it is limited to some part of
|
||||
it due to used antennas or power amplifier. An example case for this
|
||||
can be tri-band wireless router with two identical chipsets used for two
|
||||
different 5 GHz subbands. Using them incorrectly could not work or
|
||||
decrease performance noticeably
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
- |
|
||||
pcie0 {
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
wifi@0,0 {
|
||||
reg = <0x0000 0 0 0 0>;
|
||||
ieee80211-freq-limit = <2402000 2482000>,
|
||||
<5170000 5250000>;
|
||||
};
|
||||
};
|
@ -1,78 +0,0 @@
|
||||
* MediaTek mt76xx devices
|
||||
|
||||
This node provides properties for configuring the MediaTek mt76xx wireless
|
||||
device. The node is expected to be specified as a child node of the PCI
|
||||
controller to which the wireless chip is connected.
|
||||
|
||||
Alternatively, it can specify the wireless part of the MT7628/MT7688 or
|
||||
MT7622 SoC. For SoC, use the following compatible strings:
|
||||
|
||||
compatible:
|
||||
- "mediatek,mt7628-wmac" for MT7628/MT7688
|
||||
- "mediatek,mt7622-wmac" for MT7622
|
||||
|
||||
properties:
|
||||
- reg: Address and length of the register set for the device.
|
||||
- interrupts: Main device interrupt
|
||||
|
||||
MT7622 specific properties:
|
||||
- power-domains: phandle to the power domain that the WMAC is part of
|
||||
- mediatek,infracfg: phandle to the infrastructure bus fabric syscon node
|
||||
|
||||
Optional properties:
|
||||
|
||||
- ieee80211-freq-limit: See ieee80211.txt
|
||||
- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
|
||||
- big-endian: if the radio eeprom partition is written in big-endian, specify
|
||||
this property
|
||||
- mediatek,eeprom-merge-otp: Merge EEPROM data with OTP data. Can be used on
|
||||
boards where the flash calibration data is generic and specific calibration
|
||||
data should be pulled from the OTP ROM
|
||||
|
||||
The MAC address can as well be set with corresponding optional properties
|
||||
defined in net/ethernet.txt.
|
||||
|
||||
Optional nodes:
|
||||
- led: Properties for a connected LED
|
||||
Optional properties:
|
||||
- led-sources: See Documentation/devicetree/bindings/leds/common.txt
|
||||
|
||||
&pcie {
|
||||
pcie0 {
|
||||
wifi@0,0 {
|
||||
compatible = "mediatek,mt76";
|
||||
reg = <0x0000 0 0 0 0>;
|
||||
ieee80211-freq-limit = <5000000 6000000>;
|
||||
mediatek,mtd-eeprom = <&factory 0x8000>;
|
||||
big-endian;
|
||||
|
||||
led {
|
||||
led-sources = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
MT7628 example:
|
||||
|
||||
wmac: wmac@10300000 {
|
||||
compatible = "mediatek,mt7628-wmac";
|
||||
reg = <0x10300000 0x100000>;
|
||||
|
||||
interrupt-parent = <&cpuintc>;
|
||||
interrupts = <6>;
|
||||
|
||||
mediatek,mtd-eeprom = <&factory 0x0000>;
|
||||
};
|
||||
|
||||
MT7622 example:
|
||||
|
||||
wmac: wmac@18000000 {
|
||||
compatible = "mediatek,mt7622-wmac";
|
||||
reg = <0 0x18000000 0 0x100000>;
|
||||
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
mediatek,infracfg = <&infracfg>;
|
||||
|
||||
power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>;
|
||||
};
|
@ -0,0 +1,121 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/mediatek,mt76.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek mt76 wireless devices Generic Binding
|
||||
|
||||
maintainers:
|
||||
- Felix Fietkau <nbd@nbd.name>
|
||||
- Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
- Ryder Lee <ryder.lee@mediatek.com>
|
||||
|
||||
description: |
|
||||
This node provides properties for configuring the MediaTek mt76xx
|
||||
wireless device. The node is expected to be specified as a child
|
||||
node of the PCI controller to which the wireless chip is connected.
|
||||
Alternatively, it can specify the wireless part of the MT7628/MT7688
|
||||
or MT7622 SoC.
|
||||
|
||||
allOf:
|
||||
- $ref: ieee80211.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt76
|
||||
- mediatek,mt7628-wmac
|
||||
- mediatek,mt7622-wmac
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the infrastructure bus fabric syscon node.
|
||||
This property is MT7622 specific
|
||||
|
||||
ieee80211-freq-limit: true
|
||||
|
||||
mediatek,mtd-eeprom:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description:
|
||||
Phandle to a MTD partition + offset containing EEPROM data
|
||||
|
||||
big-endian:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Specify if the radio eeprom partition is written in big-endian
|
||||
|
||||
mediatek,eeprom-merge-otp:
|
||||
type: boolean
|
||||
description:
|
||||
Merge EEPROM data with OTP data. Can be used on boards where the flash
|
||||
calibration data is generic and specific calibration data should be
|
||||
pulled from the OTP ROM
|
||||
|
||||
led:
|
||||
type: object
|
||||
$ref: /schemas/leds/common.yaml#
|
||||
additionalProperties: false
|
||||
properties:
|
||||
led-sources:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pcie0 {
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
wifi@0,0 {
|
||||
compatible = "mediatek,mt76";
|
||||
reg = <0x0000 0 0 0 0>;
|
||||
ieee80211-freq-limit = <5000000 6000000>;
|
||||
mediatek,mtd-eeprom = <&factory 0x8000>;
|
||||
big-endian;
|
||||
|
||||
led {
|
||||
led-sources = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
wifi@10300000 {
|
||||
compatible = "mediatek,mt7628-wmac";
|
||||
reg = <0x10300000 0x100000>;
|
||||
|
||||
interrupt-parent = <&cpuintc>;
|
||||
interrupts = <6>;
|
||||
|
||||
mediatek,mtd-eeprom = <&factory 0x0>;
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
wifi@18000000 {
|
||||
compatible = "mediatek,mt7622-wmac";
|
||||
reg = <0x10300000 0x100000>;
|
||||
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
mediatek,infracfg = <&infracfg>;
|
||||
|
||||
power-domains = <&scpsys 3>;
|
||||
};
|
@ -76,7 +76,7 @@ mt76_rx_aggr_check_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames)
|
||||
|
||||
nframes--;
|
||||
status = (struct mt76_rx_status *)skb->cb;
|
||||
if (!time_after(jiffies,
|
||||
if (!time_after32(jiffies,
|
||||
status->reorder_time +
|
||||
mt76_aggr_tid_to_timeo(tid->num)))
|
||||
continue;
|
||||
@ -122,6 +122,7 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
|
||||
struct ieee80211_bar *bar = mt76_skb_get_hdr(skb);
|
||||
struct mt76_wcid *wcid = status->wcid;
|
||||
struct mt76_rx_tid *tid;
|
||||
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u16 seqno;
|
||||
|
||||
if (!ieee80211_is_ctl(bar->frame_control))
|
||||
@ -130,9 +131,9 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
|
||||
if (!ieee80211_is_back_req(bar->frame_control))
|
||||
return;
|
||||
|
||||
status->tid = le16_to_cpu(bar->control) >> 12;
|
||||
status->qos_ctl = tidno = le16_to_cpu(bar->control) >> 12;
|
||||
seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num));
|
||||
tid = rcu_dereference(wcid->aggr[status->tid]);
|
||||
tid = rcu_dereference(wcid->aggr[tidno]);
|
||||
if (!tid)
|
||||
return;
|
||||
|
||||
@ -147,12 +148,12 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
|
||||
void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
|
||||
struct mt76_wcid *wcid = status->wcid;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_rx_tid *tid;
|
||||
bool sn_less;
|
||||
u16 seqno, head, size, idx;
|
||||
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u8 ackp;
|
||||
|
||||
__skb_queue_tail(frames, skb);
|
||||
@ -161,18 +162,18 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
|
||||
if (!sta)
|
||||
return;
|
||||
|
||||
if (!status->aggr) {
|
||||
if (!status->aggr && !(status->flag & RX_FLAG_8023)) {
|
||||
mt76_rx_aggr_check_ctl(skb, frames);
|
||||
return;
|
||||
}
|
||||
|
||||
/* not part of a BA session */
|
||||
ackp = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
|
||||
ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
|
||||
if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
|
||||
ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
|
||||
return;
|
||||
|
||||
tid = rcu_dereference(wcid->aggr[status->tid]);
|
||||
tid = rcu_dereference(wcid->aggr[tidno]);
|
||||
if (!tid)
|
||||
return;
|
||||
|
||||
|
@ -79,13 +79,38 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
writel(q->ndesc, &q->regs->ring_size);
|
||||
q->head = readl(&q->regs->dma_idx);
|
||||
q->tail = q->head;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!q)
|
||||
return;
|
||||
|
||||
/* clear descriptors */
|
||||
for (i = 0; i < q->ndesc; i++)
|
||||
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
|
||||
|
||||
writel(0, &q->regs->cpu_idx);
|
||||
writel(0, &q->regs->dma_idx);
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc, int bufsize,
|
||||
u32 ring_base)
|
||||
{
|
||||
int size;
|
||||
int i;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
spin_lock_init(&q->cleanup_lock);
|
||||
@ -105,14 +130,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (!q->entry)
|
||||
return -ENOMEM;
|
||||
|
||||
/* clear descriptors */
|
||||
for (i = 0; i < q->ndesc; i++)
|
||||
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
|
||||
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
writel(0, &q->regs->cpu_idx);
|
||||
writel(0, &q->regs->dma_idx);
|
||||
writel(q->ndesc, &q->regs->ring_size);
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -201,15 +219,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
||||
memset(e, 0, sizeof(*e));
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
writel(q->ndesc, &q->regs->ring_size);
|
||||
q->head = readl(&q->regs->dma_idx);
|
||||
q->tail = q->head;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
@ -309,7 +318,7 @@ static int
|
||||
mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, u32 tx_info)
|
||||
{
|
||||
struct mt76_queue_buf buf;
|
||||
struct mt76_queue_buf buf = {};
|
||||
dma_addr_t addr;
|
||||
|
||||
if (q->queued + 1 >= q->ndesc - 1)
|
||||
@ -602,7 +611,6 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)
|
||||
dev = container_of(napi->dev, struct mt76_dev, napi_dev);
|
||||
qid = napi - dev->napi;
|
||||
|
||||
local_bh_disable();
|
||||
rcu_read_lock();
|
||||
|
||||
do {
|
||||
@ -612,7 +620,6 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)
|
||||
} while (cur && done < budget);
|
||||
|
||||
rcu_read_unlock();
|
||||
local_bh_enable();
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
dev->drv->rx_poll_complete(dev, qid);
|
||||
@ -626,6 +633,10 @@ mt76_dma_init(struct mt76_dev *dev)
|
||||
int i;
|
||||
|
||||
init_dummy_netdev(&dev->napi_dev);
|
||||
init_dummy_netdev(&dev->tx_napi_dev);
|
||||
snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s",
|
||||
wiphy_name(dev->hw->wiphy));
|
||||
dev->napi_dev.threaded = 1;
|
||||
|
||||
mt76_for_each_q_rx(dev, i) {
|
||||
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
|
||||
@ -640,9 +651,11 @@ mt76_dma_init(struct mt76_dev *dev)
|
||||
static const struct mt76_queue_ops mt76_dma_ops = {
|
||||
.init = mt76_dma_init,
|
||||
.alloc = mt76_dma_alloc_queue,
|
||||
.reset_q = mt76_dma_queue_reset,
|
||||
.tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
|
||||
.tx_queue_skb = mt76_dma_tx_queue_skb,
|
||||
.tx_cleanup = mt76_dma_tx_cleanup,
|
||||
.rx_cleanup = mt76_dma_rx_cleanup,
|
||||
.rx_reset = mt76_dma_rx_reset,
|
||||
.kick = mt76_dma_kick_queue,
|
||||
};
|
||||
|
@ -508,6 +508,39 @@ void mt76_free_device(struct mt76_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
|
||||
static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
|
||||
{
|
||||
struct sk_buff *skb = phy->rx_amsdu[q].head;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
|
||||
phy->rx_amsdu[q].head = NULL;
|
||||
phy->rx_amsdu[q].tail = NULL;
|
||||
__skb_queue_tail(&dev->rx_skb[q], skb);
|
||||
}
|
||||
|
||||
static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
|
||||
if (phy->rx_amsdu[q].head &&
|
||||
(!status->amsdu || status->first_amsdu ||
|
||||
status->seqno != phy->rx_amsdu[q].seqno))
|
||||
mt76_rx_release_amsdu(phy, q);
|
||||
|
||||
if (!phy->rx_amsdu[q].head) {
|
||||
phy->rx_amsdu[q].tail = &skb_shinfo(skb)->frag_list;
|
||||
phy->rx_amsdu[q].seqno = status->seqno;
|
||||
phy->rx_amsdu[q].head = skb;
|
||||
} else {
|
||||
*phy->rx_amsdu[q].tail = skb;
|
||||
phy->rx_amsdu[q].tail = &skb->next;
|
||||
}
|
||||
|
||||
if (!status->amsdu || status->last_amsdu)
|
||||
mt76_rx_release_amsdu(phy, q);
|
||||
}
|
||||
|
||||
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
@ -525,7 +558,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
|
||||
phy->test.rx_stats.fcs_error[q]++;
|
||||
}
|
||||
#endif
|
||||
__skb_queue_tail(&dev->rx_skb[q], skb);
|
||||
|
||||
mt76_rx_release_burst(phy, q, skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_rx);
|
||||
|
||||
@ -720,6 +754,8 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
status->signal = mstat.signal;
|
||||
status->chains = mstat.chains;
|
||||
status->ampdu_reference = mstat.ampdu_ref;
|
||||
status->device_timestamp = mstat.timestamp;
|
||||
status->mactime = mstat.timestamp;
|
||||
|
||||
BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb));
|
||||
BUILD_BUG_ON(sizeof(status->chain_signal) !=
|
||||
@ -737,6 +773,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct mt76_wcid *wcid = status->wcid;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
int ret;
|
||||
|
||||
if (!(status->flag & RX_FLAG_DECRYPTED))
|
||||
@ -757,12 +794,12 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
|
||||
ret = memcmp(status->iv, wcid->rx_key_pn[status->tid],
|
||||
ret = memcmp(status->iv, wcid->rx_key_pn[tidno],
|
||||
sizeof(status->iv));
|
||||
if (ret <= 0)
|
||||
return -EINVAL; /* replay */
|
||||
|
||||
memcpy(wcid->rx_key_pn[status->tid], status->iv, sizeof(status->iv));
|
||||
memcpy(wcid->rx_key_pn[tidno], status->iv, sizeof(status->iv));
|
||||
|
||||
if (status->flag & RX_FLAG_IV_STRIPPED)
|
||||
status->flag |= RX_FLAG_PN_VALIDATED;
|
||||
@ -785,6 +822,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status,
|
||||
};
|
||||
struct ieee80211_sta *sta;
|
||||
u32 airtime;
|
||||
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
||||
airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len);
|
||||
spin_lock(&dev->cc_lock);
|
||||
@ -795,7 +833,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status,
|
||||
return;
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
||||
ieee80211_sta_register_airtime(sta, status->tid, 0, airtime);
|
||||
ieee80211_sta_register_airtime(sta, tidno, 0, airtime);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -823,7 +861,6 @@ mt76_airtime_flush_ampdu(struct mt76_dev *dev)
|
||||
static void
|
||||
mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct mt76_wcid *wcid = status->wcid;
|
||||
|
||||
@ -831,6 +868,11 @@ mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
return;
|
||||
|
||||
if (!wcid || !wcid->sta) {
|
||||
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
|
||||
|
||||
if (status->flag & RX_FLAG_8023)
|
||||
return;
|
||||
|
||||
if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr))
|
||||
return;
|
||||
|
||||
@ -864,10 +906,12 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_hw *hw;
|
||||
struct mt76_wcid *wcid = status->wcid;
|
||||
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
bool ps;
|
||||
|
||||
hw = mt76_phy_hw(dev, status->ext_phy);
|
||||
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) {
|
||||
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid &&
|
||||
!(status->flag & RX_FLAG_8023)) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
|
||||
if (sta)
|
||||
wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
@ -885,6 +929,9 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
|
||||
wcid->inactive_count = 0;
|
||||
|
||||
if (status->flag & RX_FLAG_8023)
|
||||
return;
|
||||
|
||||
if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
|
||||
return;
|
||||
|
||||
@ -902,7 +949,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
|
||||
if (ps && (ieee80211_is_data_qos(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control)))
|
||||
ieee80211_sta_uapsd_trigger(sta, status->tid);
|
||||
ieee80211_sta_uapsd_trigger(sta, tidno);
|
||||
|
||||
if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps)
|
||||
return;
|
||||
@ -926,13 +973,26 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
|
||||
|
||||
spin_lock(&dev->rx_lock);
|
||||
while ((skb = __skb_dequeue(frames)) != NULL) {
|
||||
struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
|
||||
|
||||
if (mt76_check_ccmp_pn(skb)) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
mt76_rx_convert(dev, skb, &hw, &sta);
|
||||
ieee80211_rx_list(hw, sta, skb, &list);
|
||||
|
||||
/* subsequent amsdu frames */
|
||||
while (nskb) {
|
||||
skb = nskb;
|
||||
nskb = nskb->next;
|
||||
skb->next = NULL;
|
||||
|
||||
mt76_rx_convert(dev, skb, &hw, &sta);
|
||||
ieee80211_rx_list(hw, sta, skb, &list);
|
||||
}
|
||||
}
|
||||
spin_unlock(&dev->rx_lock);
|
||||
|
||||
|
@ -99,6 +99,10 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
dev_kfree_skb(skb);
|
||||
} while (ret == -EAGAIN);
|
||||
|
||||
/* notify driver code to reset the mcu */
|
||||
if (ret == -ETIMEDOUT && dev->mcu_ops->mcu_reset)
|
||||
dev->mcu_ops->mcu_reset(dev);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mcu.mutex);
|
||||
|
||||
|
@ -166,6 +166,7 @@ struct mt76_mcu_ops {
|
||||
int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base,
|
||||
struct mt76_reg_pair *rp, int len);
|
||||
int (*mcu_restart)(struct mt76_dev *dev);
|
||||
void (*mcu_reset)(struct mt76_dev *dev);
|
||||
};
|
||||
|
||||
struct mt76_queue_ops {
|
||||
@ -190,13 +191,18 @@ struct mt76_queue_ops {
|
||||
void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool flush);
|
||||
|
||||
void (*rx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
|
||||
void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
|
||||
void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
};
|
||||
|
||||
enum mt76_wcid_flags {
|
||||
MT_WCID_FLAG_CHECK_PS,
|
||||
MT_WCID_FLAG_PS,
|
||||
MT_WCID_FLAG_4ADDR,
|
||||
MT_WCID_FLAG_HDR_TRANS,
|
||||
};
|
||||
|
||||
#define MT76_N_WCIDS 288
|
||||
@ -222,6 +228,7 @@ struct mt76_wcid {
|
||||
|
||||
u16 idx;
|
||||
u8 hw_key_idx;
|
||||
u8 hw_key_idx2;
|
||||
|
||||
u8 sta:1;
|
||||
u8 ext_phy:1;
|
||||
@ -491,15 +498,16 @@ struct mt76_rx_status {
|
||||
u16 wcid_idx;
|
||||
};
|
||||
|
||||
unsigned long reorder_time;
|
||||
u32 reorder_time;
|
||||
|
||||
u32 ampdu_ref;
|
||||
u32 timestamp;
|
||||
|
||||
u8 iv[6];
|
||||
|
||||
u8 ext_phy:1;
|
||||
u8 aggr:1;
|
||||
u8 tid;
|
||||
u8 qos_ctl;
|
||||
u16 seqno;
|
||||
|
||||
u16 freq;
|
||||
@ -507,6 +515,7 @@ struct mt76_rx_status {
|
||||
u8 enc_flags;
|
||||
u8 encoding:2, bw:3, he_ru:3;
|
||||
u8 he_gi:2, he_dcm:1;
|
||||
u8 amsdu:1, first_amsdu:1, last_amsdu:1;
|
||||
u8 rate_idx;
|
||||
u8 nss;
|
||||
u8 band;
|
||||
@ -600,6 +609,12 @@ struct mt76_phy {
|
||||
|
||||
struct delayed_work mac_work;
|
||||
u8 mac_work_count;
|
||||
|
||||
struct {
|
||||
struct sk_buff *head;
|
||||
struct sk_buff **tail;
|
||||
u16 seqno;
|
||||
} rx_amsdu[__MT_RXQ_MAX];
|
||||
};
|
||||
|
||||
struct mt76_dev {
|
||||
@ -628,6 +643,7 @@ struct mt76_dev {
|
||||
struct mt76_mcu mcu;
|
||||
|
||||
struct net_device napi_dev;
|
||||
struct net_device tx_napi_dev;
|
||||
spinlock_t rx_lock;
|
||||
struct napi_struct napi[__MT_RXQ_MAX];
|
||||
struct sk_buff_head rx_skb[__MT_RXQ_MAX];
|
||||
@ -784,7 +800,9 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
|
||||
#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__)
|
||||
|
||||
#define mt76_for_each_q_rx(dev, i) \
|
||||
for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \
|
||||
|
@ -223,7 +223,7 @@ int mt7603_dma_init(struct mt7603_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7603_poll_tx, NAPI_POLL_WEIGHT);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
|
@ -548,6 +548,9 @@ int mt7603_register_device(struct mt7603_dev *dev)
|
||||
hw->max_report_rates = 7;
|
||||
hw->max_rate_tries = 11;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||
|
||||
hw->sta_data_size = sizeof(struct mt7603_sta);
|
||||
hw->vif_data_size = sizeof(struct mt7603_vif);
|
||||
|
||||
|
@ -532,20 +532,6 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
|
||||
status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
|
||||
}
|
||||
|
||||
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
|
||||
MT_RXD2_NORMAL_NON_AMPDU))) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (dev->rx_ampdu_ts != rxd[12]) {
|
||||
if (!++dev->ampdu_ref)
|
||||
dev->ampdu_ref++;
|
||||
}
|
||||
dev->rx_ampdu_ts = rxd[12];
|
||||
|
||||
status->ampdu_ref = dev->ampdu_ref;
|
||||
}
|
||||
|
||||
remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;
|
||||
|
||||
if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
|
||||
@ -579,6 +565,23 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {
|
||||
status->timestamp = le32_to_cpu(rxd[0]);
|
||||
status->flag |= RX_FLAG_MACTIME_START;
|
||||
|
||||
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
|
||||
MT_RXD2_NORMAL_NON_AMPDU))) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (dev->rx_ampdu_ts != status->timestamp) {
|
||||
if (!++dev->ampdu_ref)
|
||||
dev->ampdu_ref++;
|
||||
}
|
||||
dev->rx_ampdu_ts = status->timestamp;
|
||||
|
||||
status->ampdu_ref = dev->ampdu_ref;
|
||||
}
|
||||
|
||||
rxd += 2;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
@ -651,7 +654,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
|
||||
|
||||
status->aggr = unicast &&
|
||||
!ieee80211_is_qos_nullfunc(hdr->frame_control);
|
||||
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
|
||||
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
|
||||
|
||||
return 0;
|
||||
|
@ -120,7 +120,7 @@ struct mt7603_dev {
|
||||
unsigned long last_cca_adj;
|
||||
|
||||
u32 ampdu_ref;
|
||||
__le32 rx_ampdu_ts;
|
||||
u32 rx_ampdu_ts;
|
||||
u8 rssi_offset[3];
|
||||
|
||||
u8 slottime;
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "mt7603.h"
|
||||
|
||||
static const struct pci_device_id mt76pci_device_table[] = {
|
||||
{ PCI_DEVICE(0x14c3, 0x7603) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7603) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -517,7 +517,10 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
|
||||
&fops_pm_idle_timeout);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,
|
||||
mt7615_radio_read);
|
||||
debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
|
||||
|
||||
if (is_mt7615(&dev->mt76)) {
|
||||
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
|
||||
&dev->hw_pattern);
|
||||
/* test pattern knobs */
|
||||
debugfs_create_u8("pattern_len", 0600, dir,
|
||||
&dev->radar_pattern.n_pulses);
|
||||
@ -529,6 +532,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
|
||||
&dev->radar_pattern.power);
|
||||
debugfs_create_file("radar_trigger", 0200, dir, dev,
|
||||
&fops_radar_pattern);
|
||||
}
|
||||
|
||||
debugfs_create_file("reset_test", 0200, dir, dev,
|
||||
&fops_reset_test);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,
|
||||
|
@ -176,6 +176,21 @@ static void mt7663_dma_sched_init(struct mt7615_dev *dev)
|
||||
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987);
|
||||
}
|
||||
|
||||
void mt7615_dma_start(struct mt7615_dev *dev)
|
||||
{
|
||||
/* start dma engine */
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
|
||||
|
||||
if (is_mt7622(&dev->mt76))
|
||||
mt7622_dma_sched_init(dev);
|
||||
|
||||
if (is_mt7663(&dev->mt76))
|
||||
mt7663_dma_sched_init(dev);
|
||||
}
|
||||
|
||||
int mt7615_dma_init(struct mt7615_dev *dev)
|
||||
{
|
||||
int rx_ring_size = MT7615_RX_RING_SIZE;
|
||||
@ -245,7 +260,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7615_poll_tx, NAPI_POLL_WEIGHT);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
@ -253,20 +268,11 @@ int mt7615_dma_init(struct mt7615_dev *dev)
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000);
|
||||
|
||||
/* start dma engine */
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
/* enable interrupts for TX/RX rings */
|
||||
mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | mt7615_tx_mcu_int_mask(dev) |
|
||||
MT_INT_MCU_CMD);
|
||||
|
||||
if (is_mt7622(&dev->mt76))
|
||||
mt7622_dma_sched_init(dev);
|
||||
|
||||
if (is_mt7663(&dev->mt76))
|
||||
mt7663_dma_sched_init(dev);
|
||||
mt7615_dma_start(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev)
|
||||
switch (val) {
|
||||
case 0x7615:
|
||||
case 0x7622:
|
||||
case 0x7663:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -116,10 +116,10 @@ mt7615_mac_init(struct mt7615_dev *dev)
|
||||
mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN);
|
||||
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN);
|
||||
|
||||
/* disable hdr translation and hw AMSDU */
|
||||
mt76_wr(dev, MT_DMA_DCR0,
|
||||
FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) |
|
||||
MT_DMA_DCR0_RX_VEC_DROP);
|
||||
MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN |
|
||||
MT_DMA_DCR0_RX_HDR_TRANS_EN);
|
||||
/* disable TDLS filtering */
|
||||
mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN);
|
||||
mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN);
|
||||
@ -129,6 +129,7 @@ mt7615_mac_init(struct mt7615_dev *dev)
|
||||
} else {
|
||||
mt7615_init_mac_chain(dev, 1);
|
||||
}
|
||||
mt7615_mcu_set_rx_hdr_trans_blacklist(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -330,6 +331,10 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
|
||||
hw->max_rates = 3;
|
||||
hw->max_report_rates = 7;
|
||||
hw->max_rate_tries = 11;
|
||||
hw->netdev_features = NETIF_F_RXCSUM;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||
|
||||
phy->slottime = 9;
|
||||
|
||||
@ -360,11 +365,17 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
|
||||
if (is_mt7615(&phy->dev->mt76))
|
||||
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
|
||||
else
|
||||
hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
|
||||
|
||||
phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -496,16 +507,11 @@ void mt7615_init_device(struct mt7615_dev *dev)
|
||||
init_waitqueue_head(&dev->reset_wait);
|
||||
init_waitqueue_head(&dev->phy.roc_wait);
|
||||
|
||||
INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
|
||||
INIT_WORK(&dev->phy.roc_work, mt7615_roc_work);
|
||||
timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0);
|
||||
|
||||
mt7615_init_wiphy(hw);
|
||||
dev->pm.idle_timeout = MT7615_PM_TIMEOUT;
|
||||
dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
mt7615_cap_dbdc_disable(dev);
|
||||
dev->phy.dfs_state = -1;
|
||||
|
||||
|
@ -234,11 +234,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
u32 rxd0 = le32_to_cpu(rxd[0]);
|
||||
u32 rxd1 = le32_to_cpu(rxd[1]);
|
||||
u32 rxd2 = le32_to_cpu(rxd[2]);
|
||||
__le32 rxd12 = rxd[12];
|
||||
bool unicast, remove_pad, insert_ccmp_hdr = false;
|
||||
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
|
||||
bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false;
|
||||
int phy_idx;
|
||||
int i, idx;
|
||||
u8 chfreq;
|
||||
u8 chfreq, amsdu_info, qos_ctl = 0;
|
||||
u16 seq_ctrl = 0;
|
||||
__le16 fc = 0;
|
||||
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
@ -254,8 +256,12 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
else
|
||||
phy_idx = -1;
|
||||
|
||||
if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
|
||||
return -EINVAL;
|
||||
|
||||
unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M;
|
||||
idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);
|
||||
hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS;
|
||||
status->wcid = mt7615_rx_get_wcid(dev, idx, unicast);
|
||||
|
||||
if (status->wcid) {
|
||||
@ -268,6 +274,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
spin_unlock_bh(&dev->sta_poll_lock);
|
||||
}
|
||||
|
||||
if ((rxd0 & csum_mask) == csum_mask)
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
if (rxd2 & MT_RXD2_NORMAL_FCS_ERR)
|
||||
status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
@ -288,6 +297,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
|
||||
rxd += 4;
|
||||
if (rxd0 & MT_RXD0_NORMAL_GROUP_4) {
|
||||
u32 v0 = le32_to_cpu(rxd[0]);
|
||||
u32 v2 = le32_to_cpu(rxd[2]);
|
||||
|
||||
fc = cpu_to_le16(FIELD_GET(MT_RXD4_FRAME_CONTROL, v0));
|
||||
qos_ctl = FIELD_GET(MT_RXD6_QOS_CTL, v2);
|
||||
seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, v2);
|
||||
|
||||
rxd += 4;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
@ -312,6 +328,23 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {
|
||||
status->timestamp = le32_to_cpu(rxd[0]);
|
||||
status->flag |= RX_FLAG_MACTIME_START;
|
||||
|
||||
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
|
||||
MT_RXD2_NORMAL_NON_AMPDU))) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (phy->rx_ampdu_ts != status->timestamp) {
|
||||
if (!++phy->ampdu_ref)
|
||||
phy->ampdu_ref++;
|
||||
}
|
||||
phy->rx_ampdu_ts = status->timestamp;
|
||||
|
||||
status->ampdu_ref = phy->ampdu_ref;
|
||||
}
|
||||
|
||||
rxd += 2;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
@ -355,20 +388,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
if (!sband->channels)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
|
||||
MT_RXD2_NORMAL_NON_AMPDU))) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (phy->rx_ampdu_ts != rxd12) {
|
||||
if (!++phy->ampdu_ref)
|
||||
phy->ampdu_ref++;
|
||||
}
|
||||
phy->rx_ampdu_ts = rxd12;
|
||||
|
||||
status->ampdu_ref = phy->ampdu_ref;
|
||||
}
|
||||
|
||||
if (rxd0 & MT_RXD0_NORMAL_GROUP_3) {
|
||||
u32 rxdg0 = le32_to_cpu(rxd[0]);
|
||||
u32 rxdg1 = le32_to_cpu(rxd[1]);
|
||||
@ -446,20 +465,42 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
|
||||
skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
|
||||
|
||||
if (insert_ccmp_hdr) {
|
||||
amsdu_info = FIELD_GET(MT_RXD1_NORMAL_PAYLOAD_FORMAT, rxd1);
|
||||
status->amsdu = !!amsdu_info;
|
||||
if (status->amsdu) {
|
||||
status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME;
|
||||
status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME;
|
||||
if (!hdr_trans) {
|
||||
memmove(skb->data + 2, skb->data,
|
||||
ieee80211_get_hdrlen_from_skb(skb));
|
||||
skb_pull(skb, 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (insert_ccmp_hdr && !hdr_trans) {
|
||||
u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
|
||||
|
||||
mt76_insert_ccmp_hdr(skb, key_id);
|
||||
}
|
||||
|
||||
if (!hdr_trans) {
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
|
||||
fc = hdr->frame_control;
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
|
||||
qos_ctl = *ieee80211_get_qos_ctl(hdr);
|
||||
}
|
||||
} else {
|
||||
status->flag |= RX_FLAG_8023;
|
||||
}
|
||||
|
||||
if (!status->wcid || !ieee80211_is_data_qos(fc))
|
||||
return 0;
|
||||
|
||||
status->aggr = unicast &&
|
||||
!ieee80211_is_qos_nullfunc(hdr->frame_control);
|
||||
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
|
||||
!ieee80211_is_qos_nullfunc(fc);
|
||||
status->qos_ctl = qos_ctl;
|
||||
status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -690,7 +731,7 @@ mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < txp->nbuf; i++)
|
||||
for (i = 0; i < txp->nbuf; i++)
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
|
||||
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
|
||||
}
|
||||
@ -966,6 +1007,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
struct mt7615_rate_desc rd;
|
||||
u32 w5, w27, addr;
|
||||
u16 idx = sta->vif->mt76.omac_idx;
|
||||
|
||||
if (!mt76_is_mmio(&dev->mt76)) {
|
||||
mt7615_mac_queue_rate_update(phy, sta, probe_rate, rates);
|
||||
@ -1017,7 +1059,10 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
|
||||
|
||||
mt76_wr(dev, addr + 27 * 4, w27);
|
||||
|
||||
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */
|
||||
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
|
||||
addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
|
||||
|
||||
mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
|
||||
sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0);
|
||||
sta->rate_set_tsf |= rd.rateset;
|
||||
|
||||
@ -1033,7 +1078,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
|
||||
static int
|
||||
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key,
|
||||
enum mt7615_cipher_type cipher,
|
||||
enum mt7615_cipher_type cipher, u16 cipher_mask,
|
||||
enum set_key_cmd cmd)
|
||||
{
|
||||
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
|
||||
@ -1050,22 +1095,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
memcpy(data + 16, key->key + 24, 8);
|
||||
memcpy(data + 24, key->key + 16, 8);
|
||||
} else {
|
||||
if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher)
|
||||
memmove(data + 16, data, 16);
|
||||
if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher)
|
||||
if (cipher_mask == BIT(cipher))
|
||||
memcpy(data, key->key, key->keylen);
|
||||
else if (cipher == MT_CIPHER_BIP_CMAC_128)
|
||||
else if (cipher != MT_CIPHER_BIP_CMAC_128)
|
||||
memcpy(data, key->key, 16);
|
||||
if (cipher == MT_CIPHER_BIP_CMAC_128)
|
||||
memcpy(data + 16, key->key, 16);
|
||||
}
|
||||
} else {
|
||||
if (wcid->cipher & ~BIT(cipher)) {
|
||||
if (cipher != MT_CIPHER_BIP_CMAC_128)
|
||||
memmove(data, data + 16, 16);
|
||||
if (cipher == MT_CIPHER_BIP_CMAC_128)
|
||||
memset(data + 16, 0, 16);
|
||||
} else {
|
||||
else if (cipher_mask)
|
||||
memset(data, 0, 16);
|
||||
if (!cipher_mask)
|
||||
memset(data, 0, sizeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
mt76_wr_copy(dev, addr, data, sizeof(data));
|
||||
|
||||
return 0;
|
||||
@ -1073,7 +1118,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
|
||||
static int
|
||||
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
enum mt7615_cipher_type cipher,
|
||||
enum mt7615_cipher_type cipher, u16 cipher_mask,
|
||||
int keyidx, enum set_key_cmd cmd)
|
||||
{
|
||||
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
|
||||
@ -1083,20 +1128,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
|
||||
w0 = mt76_rr(dev, addr);
|
||||
w1 = mt76_rr(dev, addr + 4);
|
||||
if (cmd == SET_KEY) {
|
||||
w0 |= MT_WTBL_W0_RX_KEY_VALID |
|
||||
FIELD_PREP(MT_WTBL_W0_RX_IK_VALID,
|
||||
cipher == MT_CIPHER_BIP_CMAC_128);
|
||||
if (cipher != MT_CIPHER_BIP_CMAC_128 ||
|
||||
!wcid->cipher)
|
||||
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
|
||||
} else {
|
||||
if (!(wcid->cipher & ~BIT(cipher)))
|
||||
w0 &= ~(MT_WTBL_W0_RX_KEY_VALID |
|
||||
MT_WTBL_W0_KEY_IDX);
|
||||
if (cipher == MT_CIPHER_BIP_CMAC_128)
|
||||
|
||||
if (cipher_mask)
|
||||
w0 |= MT_WTBL_W0_RX_KEY_VALID;
|
||||
else
|
||||
w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX);
|
||||
if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128))
|
||||
w0 |= MT_WTBL_W0_RX_IK_VALID;
|
||||
else
|
||||
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
|
||||
|
||||
if (cmd == SET_KEY &&
|
||||
(cipher != MT_CIPHER_BIP_CMAC_128 ||
|
||||
cipher_mask == BIT(cipher))) {
|
||||
w0 &= ~MT_WTBL_W0_KEY_IDX;
|
||||
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
|
||||
}
|
||||
|
||||
mt76_wr(dev, MT_WTBL_RICR0, w0);
|
||||
mt76_wr(dev, MT_WTBL_RICR1, w1);
|
||||
|
||||
@ -1109,24 +1157,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
|
||||
static void
|
||||
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
enum mt7615_cipher_type cipher,
|
||||
enum mt7615_cipher_type cipher, u16 cipher_mask,
|
||||
enum set_key_cmd cmd)
|
||||
{
|
||||
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher)
|
||||
if (!cipher_mask) {
|
||||
mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd != SET_KEY)
|
||||
return;
|
||||
|
||||
if (cipher == MT_CIPHER_BIP_CMAC_128 &&
|
||||
cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
|
||||
return;
|
||||
|
||||
mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
|
||||
FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher));
|
||||
} else {
|
||||
if (cipher != MT_CIPHER_BIP_CMAC_128 &&
|
||||
wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128))
|
||||
mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
|
||||
FIELD_PREP(MT_WTBL_W2_KEY_TYPE,
|
||||
MT_CIPHER_BIP_CMAC_128));
|
||||
else if (!(wcid->cipher & ~BIT(cipher)))
|
||||
mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
||||
@ -1135,25 +1184,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
||||
enum set_key_cmd cmd)
|
||||
{
|
||||
enum mt7615_cipher_type cipher;
|
||||
u16 cipher_mask = wcid->cipher;
|
||||
int err;
|
||||
|
||||
cipher = mt7615_mac_get_cipher(key->cipher);
|
||||
if (cipher == MT_CIPHER_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd);
|
||||
err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (cmd == SET_KEY)
|
||||
wcid->cipher |= BIT(cipher);
|
||||
cipher_mask |= BIT(cipher);
|
||||
else
|
||||
wcid->cipher &= ~BIT(cipher);
|
||||
cipher_mask &= ~BIT(cipher);
|
||||
|
||||
mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
|
||||
err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
|
||||
cmd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
|
||||
key->keyidx, cmd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
wcid->cipher = cipher_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1821,9 +1875,7 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy)
|
||||
int i, aggr;
|
||||
u32 val, val2;
|
||||
|
||||
memset(mib, 0, sizeof(*mib));
|
||||
|
||||
mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
|
||||
mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
|
||||
MT_MIB_SDR3_FCS_ERR_MASK);
|
||||
|
||||
val = mt76_get_field(dev, MT_MIB_SDR14(ext_phy),
|
||||
@ -1837,24 +1889,16 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy)
|
||||
aggr = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i));
|
||||
|
||||
val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
|
||||
if (val2 > mib->ack_fail_cnt)
|
||||
mib->ack_fail_cnt = val2;
|
||||
|
||||
val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
|
||||
if (val2 > mib->ba_miss_cnt)
|
||||
mib->ba_miss_cnt = val2;
|
||||
mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
|
||||
mib->ack_fail_cnt += FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK,
|
||||
val);
|
||||
|
||||
val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i));
|
||||
val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
|
||||
if (val2 > mib->rts_retries_cnt) {
|
||||
mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
|
||||
mib->rts_retries_cnt = val2;
|
||||
}
|
||||
mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
|
||||
mib->rts_retries_cnt += FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK,
|
||||
val);
|
||||
|
||||
val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));
|
||||
|
||||
dev->mt76.aggr_stats[aggr++] += val & 0xffff;
|
||||
dev->mt76.aggr_stats[aggr++] += val >> 16;
|
||||
}
|
||||
@ -1924,74 +1968,6 @@ void mt7615_mac_work(struct work_struct *work)
|
||||
MT7615_WATCHDOG_TIME);
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
ret = wait_event_timeout(dev->reset_wait,
|
||||
(READ_ONCE(dev->reset_state) & state),
|
||||
MT7615_RESET_TIMEOUT);
|
||||
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv;
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
mt7615_mcu_add_beacon(dev, hw, vif,
|
||||
vif->bss_conf.enable_beacon);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_update_beacons(struct mt7615_dev *dev)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_update_vif_beacon, dev->mt76.hw);
|
||||
|
||||
if (!dev->mt76.phy2)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_update_vif_beacon, dev->mt76.phy2->hw);
|
||||
}
|
||||
|
||||
void mt7615_dma_reset(struct mt7615_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
}
|
||||
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_dma_reset);
|
||||
|
||||
void mt7615_tx_token_put(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *txwi;
|
||||
@ -2009,94 +1985,6 @@ void mt7615_tx_token_put(struct mt7615_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_tx_token_put);
|
||||
|
||||
void mt7615_mac_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7615_phy *phy2;
|
||||
struct mt76_phy *ext_phy;
|
||||
struct mt7615_dev *dev;
|
||||
|
||||
dev = container_of(work, struct mt7615_dev, reset_work);
|
||||
ext_phy = dev->mt76.phy2;
|
||||
phy2 = ext_phy ? ext_phy->priv : NULL;
|
||||
|
||||
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
|
||||
return;
|
||||
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
if (ext_phy)
|
||||
ieee80211_stop_queues(ext_phy->hw);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
del_timer_sync(&dev->phy.roc_timer);
|
||||
cancel_work_sync(&dev->phy.roc_work);
|
||||
if (phy2) {
|
||||
cancel_delayed_work_sync(&phy2->mt76->mac_work);
|
||||
del_timer_sync(&phy2->roc_timer);
|
||||
cancel_work_sync(&phy2->roc_work);
|
||||
}
|
||||
|
||||
/* lock/unlock all queues to ensure that no tx is pending */
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
if (ext_phy)
|
||||
mt76_txq_schedule_all(ext_phy);
|
||||
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
napi_disable(&dev->mt76.napi[0]);
|
||||
napi_disable(&dev->mt76.napi[1]);
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED);
|
||||
|
||||
mt7615_tx_token_put(dev);
|
||||
idr_init(&dev->token);
|
||||
|
||||
if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
|
||||
mt7615_dma_reset(dev);
|
||||
|
||||
mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_INIT);
|
||||
mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
|
||||
}
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
|
||||
napi_enable(&dev->mt76.napi[0]);
|
||||
napi_schedule(&dev->mt76.napi[0]);
|
||||
|
||||
napi_enable(&dev->mt76.napi[1]);
|
||||
napi_schedule(&dev->mt76.napi[1]);
|
||||
|
||||
ieee80211_wake_queues(mt76_hw(dev));
|
||||
if (ext_phy)
|
||||
ieee80211_wake_queues(ext_phy->hw);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
|
||||
mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
|
||||
|
||||
mt7615_update_beacons(dev);
|
||||
|
||||
mt7615_mutex_release(dev);
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
|
||||
MT7615_WATCHDOG_TIME);
|
||||
if (phy2)
|
||||
ieee80211_queue_delayed_work(ext_phy->hw,
|
||||
&phy2->mt76->mac_work,
|
||||
MT7615_WATCHDOG_TIME);
|
||||
|
||||
}
|
||||
|
||||
static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy)
|
||||
{
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
@ -2304,8 +2192,10 @@ void mt7615_coredump_work(struct work_struct *work)
|
||||
break;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
|
||||
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ)
|
||||
break;
|
||||
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(data, skb->data, skb->len);
|
||||
data += skb->len;
|
||||
|
@ -33,6 +33,9 @@ enum rx_pkt_type {
|
||||
|
||||
#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26)
|
||||
#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24)
|
||||
#define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0)
|
||||
#define MT_RXD1_MID_AMSDU_FRAME BIT(1)
|
||||
#define MT_RXD1_LAST_AMSDU_FRAME BIT(0)
|
||||
#define MT_RXD1_NORMAL_HDR_TRANS BIT(23)
|
||||
#define MT_RXD1_NORMAL_HDR_OFFSET BIT(22)
|
||||
#define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16)
|
||||
@ -78,6 +81,11 @@ enum rx_pkt_type {
|
||||
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8)
|
||||
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
|
||||
|
||||
#define MT_RXD4_FRAME_CONTROL GENMASK(15, 0)
|
||||
|
||||
#define MT_RXD6_SEQ_CTRL GENMASK(15, 0)
|
||||
#define MT_RXD6_QOS_CTL GENMASK(31, 16)
|
||||
|
||||
#define MT_RXV1_ACID_DET_H BIT(31)
|
||||
#define MT_RXV1_ACID_DET_L BIT(30)
|
||||
#define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24)
|
||||
|
@ -29,6 +29,7 @@ static int mt7615_start(struct ieee80211_hw *hw)
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
bool running;
|
||||
int ret;
|
||||
|
||||
if (!mt7615_wait_for_mcu_init(dev))
|
||||
return -EIO;
|
||||
@ -38,21 +39,38 @@ static int mt7615_start(struct ieee80211_hw *hw)
|
||||
running = mt7615_dev_running(dev);
|
||||
|
||||
if (!running) {
|
||||
mt7615_mcu_set_pm(dev, 0, 0);
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
|
||||
ret = mt7615_mcu_set_pm(dev, 0, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7615_mac_enable_nf(dev, 0);
|
||||
}
|
||||
|
||||
if (phy != &dev->phy) {
|
||||
mt7615_mcu_set_pm(dev, 1, 0);
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false);
|
||||
ret = mt7615_mcu_set_pm(dev, 1, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7615_mac_enable_nf(dev, 1);
|
||||
}
|
||||
|
||||
if (mt7615_firmware_offload(dev))
|
||||
mt76_connac_mcu_set_channel_domain(phy->mt76);
|
||||
if (mt7615_firmware_offload(dev)) {
|
||||
ret = mt76_connac_mcu_set_channel_domain(phy->mt76);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
|
||||
ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
|
||||
@ -62,9 +80,10 @@ static int mt7615_start(struct ieee80211_hw *hw)
|
||||
if (!running)
|
||||
mt7615_mac_reset_counters(dev);
|
||||
|
||||
out:
|
||||
mt7615_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7615_stop(struct ieee80211_hw *hw)
|
||||
@ -197,7 +216,9 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
||||
dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
mt7615_mcu_set_dbdc(dev);
|
||||
ret = mt7615_mcu_set_dbdc(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
idx = MT7615_WTBL_RESERVED - mvif->mt76.idx;
|
||||
|
||||
@ -217,8 +238,6 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
||||
ret = mt7615_mcu_add_dev_info(phy, vif, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7615_mac_set_beacon_filter(phy, vif, true);
|
||||
out:
|
||||
mt7615_mutex_release(dev);
|
||||
|
||||
@ -234,17 +253,17 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
int idx = msta->wcid.idx;
|
||||
|
||||
/* TODO: disable beacon for the bss */
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
|
||||
mt7615_mcu_add_bss_info(phy, vif, NULL, false);
|
||||
mt7615_mcu_sta_add(phy, vif, NULL, false);
|
||||
|
||||
mt76_testmode_reset(phy->mt76, true);
|
||||
if (vif == phy->monitor_vif)
|
||||
phy->monitor_vif = NULL;
|
||||
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
|
||||
|
||||
mt7615_mac_set_beacon_filter(phy, vif, false);
|
||||
mt7615_mcu_add_dev_info(phy, vif, false);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
@ -296,8 +315,13 @@ int mt7615_set_channel(struct mt7615_phy *phy)
|
||||
mt76_set_channel(phy->mt76);
|
||||
|
||||
if (is_mt7615(&dev->mt76) && dev->flash_eeprom) {
|
||||
mt7615_mcu_apply_rx_dcoc(phy);
|
||||
mt7615_mcu_apply_tx_dpd(phy);
|
||||
ret = mt7615_mcu_apply_rx_dcoc(phy);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7615_mcu_apply_tx_dpd(phy);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH);
|
||||
@ -306,8 +330,13 @@ int mt7615_set_channel(struct mt7615_phy *phy)
|
||||
|
||||
mt7615_mac_set_timing(phy);
|
||||
ret = mt7615_dfs_init_radar_detector(phy);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7615_mac_cca_stats_reset(phy);
|
||||
mt7615_mcu_set_sku_en(phy, true);
|
||||
ret = mt7615_mcu_set_sku_en(phy, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7615_mac_reset_counters(dev);
|
||||
phy->noise = 0;
|
||||
@ -337,7 +366,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv :
|
||||
&mvif->sta;
|
||||
struct mt76_wcid *wcid = &msta->wcid;
|
||||
int idx = key->keyidx, err;
|
||||
int idx = key->keyidx, err = 0;
|
||||
u8 *wcid_keyidx = &wcid->hw_key_idx;
|
||||
|
||||
/* The hardware does not support per-STA RX GTK, fallback
|
||||
* to software mode for these.
|
||||
@ -352,6 +382,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
/* fall back to sw encryption for unsupported ciphers */
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
wcid_keyidx = &wcid->hw_key_idx2;
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
@ -369,12 +400,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
key->hw_key_idx = wcid->idx;
|
||||
wcid->hw_key_idx = idx;
|
||||
} else if (idx == wcid->hw_key_idx) {
|
||||
wcid->hw_key_idx = -1;
|
||||
}
|
||||
if (cmd == SET_KEY)
|
||||
*wcid_keyidx = idx;
|
||||
else if (idx == *wcid_keyidx)
|
||||
*wcid_keyidx = -1;
|
||||
else
|
||||
goto out;
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
||||
cmd == SET_KEY ? key : NULL);
|
||||
|
||||
@ -383,6 +415,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
else
|
||||
err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
|
||||
|
||||
out:
|
||||
mt7615_mutex_release(dev);
|
||||
|
||||
return err;
|
||||
@ -526,11 +559,11 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
mt7615_mcu_add_bss_info(phy, vif, NULL, info->enable_beacon);
|
||||
mt7615_mcu_sta_add(phy, vif, NULL, info->enable_beacon);
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
mt7615_mcu_add_bss_info(phy, vif, NULL, true);
|
||||
mt7615_mcu_sta_add(phy, vif, NULL, true);
|
||||
|
||||
if (vif->p2p && info->enable_beacon)
|
||||
if (vif->p2p)
|
||||
mt7615_mcu_set_p2p_oppps(hw, vif);
|
||||
}
|
||||
|
||||
@ -544,6 +577,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & BSS_CHANGED_ARP_FILTER)
|
||||
mt7615_mcu_update_arp_filter(hw, vif, info);
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC)
|
||||
mt7615_mac_set_beacon_filter(phy, vif, info->assoc);
|
||||
|
||||
mt7615_mutex_release(dev);
|
||||
}
|
||||
|
||||
@ -583,15 +619,21 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
mt7615_mcu_add_bss_info(phy, vif, sta, true);
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
|
||||
err = mt7615_mcu_add_bss_info(phy, vif, sta, true);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
mt7615_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
mt7615_mcu_sta_add(&dev->phy, vif, sta, true);
|
||||
err = mt7615_mcu_sta_add(&dev->phy, vif, sta, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_mac_sta_add);
|
||||
|
||||
@ -711,13 +753,13 @@ static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
{
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
int band = phy != &dev->phy;
|
||||
int err, band = phy != &dev->phy;
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band);
|
||||
err = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band);
|
||||
mt7615_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -745,16 +787,16 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
|
||||
params->buf_size);
|
||||
mt7615_mcu_add_rx_ba(dev, params, true);
|
||||
ret = mt7615_mcu_add_rx_ba(dev, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
|
||||
mt7615_mcu_add_rx_ba(dev, params, false);
|
||||
ret = mt7615_mcu_add_rx_ba(dev, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
mt7615_mcu_add_tx_ba(dev, params, true);
|
||||
ret = mt7615_mcu_add_tx_ba(dev, params, true);
|
||||
ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid);
|
||||
ieee80211_send_bar(vif, sta->addr, tid,
|
||||
IEEE80211_SN_TO_SEQ(ssn));
|
||||
@ -762,7 +804,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
mt7615_mcu_add_tx_ba(dev, params, false);
|
||||
ret = mt7615_mcu_add_tx_ba(dev, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid);
|
||||
@ -771,7 +813,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
mt7615_mcu_add_tx_ba(dev, params, false);
|
||||
ret = mt7615_mcu_add_tx_ba(dev, params, false);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
@ -803,26 +845,38 @@ mt7615_get_stats(struct ieee80211_hw *hw,
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
struct mib_stats *mib = &phy->mib;
|
||||
|
||||
mt7615_mutex_acquire(phy->dev);
|
||||
|
||||
stats->dot11RTSSuccessCount = mib->rts_cnt;
|
||||
stats->dot11RTSFailureCount = mib->rts_retries_cnt;
|
||||
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
|
||||
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
|
||||
|
||||
memset(mib, 0, sizeof(*mib));
|
||||
|
||||
mt7615_mutex_release(phy->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64
|
||||
mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
union {
|
||||
u64 t64;
|
||||
u32 t32[2];
|
||||
} tsf;
|
||||
u16 idx = mvif->mt76.omac_idx;
|
||||
u32 reg;
|
||||
|
||||
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
|
||||
reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
|
||||
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */
|
||||
mt76_set(dev, reg, MT_LPON_TCR_MODE); /* TSF read */
|
||||
tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0);
|
||||
tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1);
|
||||
|
||||
@ -835,18 +889,24 @@ static void
|
||||
mt7615_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u64 timestamp)
|
||||
{
|
||||
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
union {
|
||||
u64 t64;
|
||||
u32 t32[2];
|
||||
} tsf = { .t64 = timestamp, };
|
||||
u16 idx = mvif->mt76.omac_idx;
|
||||
u32 reg;
|
||||
|
||||
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
|
||||
reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
|
||||
mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]);
|
||||
mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]);
|
||||
/* TSF software overwrite */
|
||||
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_WRITE);
|
||||
mt76_set(dev, reg, MT_LPON_TCR_WRITE);
|
||||
|
||||
mt7615_mutex_release(dev);
|
||||
}
|
||||
@ -1069,6 +1129,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
int err;
|
||||
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
return 0;
|
||||
@ -1077,10 +1138,26 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
|
||||
mt7615_mutex_acquire(phy->dev);
|
||||
mt7615_mcu_set_roc(phy, vif, NULL, 0);
|
||||
err = mt7615_mcu_set_roc(phy, vif, NULL, 0);
|
||||
mt7615_mutex_release(phy->dev);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
bool enabled)
|
||||
{
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
|
||||
|
||||
if (enabled)
|
||||
set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
|
||||
else
|
||||
clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
|
||||
|
||||
mt7615_mcu_sta_update_hdr_trans(dev, vif, sta);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -1183,6 +1260,7 @@ const struct ieee80211_ops mt7615_ops = {
|
||||
.sta_remove = mt7615_sta_remove,
|
||||
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
|
||||
.set_key = mt7615_set_key,
|
||||
.sta_set_decap_offload = mt7615_sta_set_decap_offload,
|
||||
.ampdu_action = mt7615_ampdu_action,
|
||||
.set_rts_threshold = mt7615_set_rts_threshold,
|
||||
.wake_tx_queue = mt7615_wake_tx_queue,
|
||||
|
@ -274,7 +274,7 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val)
|
||||
sizeof(req), false);
|
||||
}
|
||||
|
||||
static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
|
||||
void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
|
||||
{
|
||||
if (!is_mt7622(&dev->mt76))
|
||||
return;
|
||||
@ -283,6 +283,7 @@ static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
|
||||
MT_INFRACFG_MISC_AP2CONN_WAKE,
|
||||
!en * MT_INFRACFG_MISC_AP2CONN_WAKE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7622_trigger_hif_int);
|
||||
|
||||
static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)
|
||||
{
|
||||
@ -372,6 +373,23 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt7615_mcu_csa_notify *c;
|
||||
|
||||
c = (struct mt7615_mcu_csa_notify *)skb->data;
|
||||
|
||||
if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_mcu_csa_finish, mphy->hw);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
@ -380,7 +398,7 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
|
||||
r = (struct mt7615_mcu_rdd_report *)skb->data;
|
||||
|
||||
if (r->idx && dev->mt76.phy2)
|
||||
if (r->band_idx && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
ieee80211_radar_detected(mphy->hw);
|
||||
@ -406,7 +424,8 @@ mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
|
||||
wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data);
|
||||
wiphy_info(mt76_hw(dev)->wiphy, "%s: %*s", type,
|
||||
(int)(skb->len - sizeof(*rxd)), data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -419,9 +438,7 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
|
||||
mt7615_mcu_rx_radar_detected(dev, skb);
|
||||
break;
|
||||
case MCU_EXT_EVENT_CSA_NOTIFY:
|
||||
ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_mcu_csa_finish, dev);
|
||||
mt7615_mcu_rx_csa_notify(dev, skb);
|
||||
break;
|
||||
case MCU_EXT_EVENT_FW_LOG_2_HOST:
|
||||
mt7615_mcu_rx_log_message(dev, skb);
|
||||
@ -685,6 +702,9 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
skb = ieee80211_beacon_get_template(hw, vif, &offs);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
@ -714,6 +734,7 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
out:
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
@ -973,7 +994,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
|
||||
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable);
|
||||
if (enable && sta)
|
||||
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif);
|
||||
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0);
|
||||
|
||||
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
|
||||
WTBL_RESET_AND_SET, NULL,
|
||||
@ -987,6 +1008,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
|
||||
NULL, wtbl_hdr);
|
||||
mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, &msta->wcid, NULL,
|
||||
wtbl_hdr);
|
||||
}
|
||||
|
||||
cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE;
|
||||
@ -1040,6 +1063,9 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev,
|
||||
|
||||
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
|
||||
WTBL_SET, sta_wtbl, &skb);
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx,
|
||||
sta_wtbl, wtbl_hdr);
|
||||
|
||||
@ -1068,10 +1094,15 @@ __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enable, int cmd)
|
||||
{
|
||||
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
|
||||
struct mt76_wcid *wcid;
|
||||
struct mt76_sta_cmd_info info = {
|
||||
.sta = sta,
|
||||
.vif = vif,
|
||||
.enable = enable,
|
||||
.cmd = cmd,
|
||||
};
|
||||
|
||||
wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
|
||||
return mt76_connac_mcu_add_sta_cmd(phy, vif, sta, wcid, enable, cmd);
|
||||
info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
|
||||
return mt76_connac_mcu_add_sta_cmd(phy, &info);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1094,6 +1125,25 @@ static const struct mt7615_mcu_ops sta_update_ops = {
|
||||
.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
|
||||
};
|
||||
|
||||
int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
|
||||
struct wtbl_req_hdr *wtbl_hdr;
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
|
||||
WTBL_SET, NULL, &skb);
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, &msta->wcid, NULL, wtbl_hdr);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
|
||||
true);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
|
||||
{
|
||||
@ -1120,8 +1170,8 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
|
||||
__le16 tim_ie_pos;
|
||||
__le16 csa_ie_pos;
|
||||
__le16 bcc_ie_pos;
|
||||
/* 0: enable beacon offload
|
||||
* 1: disable beacon offload
|
||||
/* 0: disable beacon offload
|
||||
* 1: enable beacon offload
|
||||
* 2: update probe respond offload
|
||||
*/
|
||||
u8 enable;
|
||||
@ -1144,6 +1194,9 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
@ -1168,6 +1221,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
out:
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE,
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
@ -1427,8 +1481,7 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name)
|
||||
sizeof(dev->mt76.hw->wiphy->fw_version),
|
||||
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
|
||||
|
||||
if (!is_mt7615(&dev->mt76) &&
|
||||
!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) {
|
||||
if (!is_mt7615(&dev->mt76)) {
|
||||
dev->fw_ver = MT7615_FIRMWARE_V2;
|
||||
dev->mcu_ops = &sta_update_ops;
|
||||
} else {
|
||||
@ -2155,7 +2208,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
|
||||
.center_chan2 = ieee80211_frequency_to_channel(freq2),
|
||||
};
|
||||
|
||||
if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
|
||||
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
|
||||
@ -2497,6 +2550,26 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev)
|
||||
{
|
||||
struct {
|
||||
u8 operation;
|
||||
u8 count;
|
||||
u8 _rsv[2];
|
||||
u8 index;
|
||||
u8 enable;
|
||||
__le16 etype;
|
||||
} req = {
|
||||
.operation = 1,
|
||||
.count = 1,
|
||||
.enable = 1,
|
||||
.etype = cpu_to_le16(ETH_P_PAE),
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS,
|
||||
&req, sizeof(req), false);
|
||||
}
|
||||
|
||||
int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
|
@ -176,10 +176,18 @@ struct mt7615_mcu_rxd {
|
||||
u8 s2d_index;
|
||||
};
|
||||
|
||||
struct mt7615_mcu_csa_notify {
|
||||
struct mt7615_mcu_rxd rxd;
|
||||
|
||||
u8 omac_idx;
|
||||
u8 csa_count;
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7615_mcu_rdd_report {
|
||||
struct mt7615_mcu_rxd rxd;
|
||||
|
||||
u8 idx;
|
||||
u8 band_idx;
|
||||
u8 long_detected;
|
||||
u8 constant_prf_detected;
|
||||
u8 staggered_prf_detected;
|
||||
@ -362,30 +370,6 @@ enum {
|
||||
BSS_INFO_MAX_NUM
|
||||
};
|
||||
|
||||
#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
|
||||
sizeof(struct wtbl_generic) + \
|
||||
sizeof(struct wtbl_rx) + \
|
||||
sizeof(struct wtbl_ht) + \
|
||||
sizeof(struct wtbl_vht) + \
|
||||
sizeof(struct wtbl_tx_ps) + \
|
||||
sizeof(struct wtbl_hdr_trans) +\
|
||||
sizeof(struct wtbl_ba) + \
|
||||
sizeof(struct wtbl_bf) + \
|
||||
sizeof(struct wtbl_smps) + \
|
||||
sizeof(struct wtbl_pn) + \
|
||||
sizeof(struct wtbl_spe))
|
||||
|
||||
#define MT7615_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct sta_rec_basic) + \
|
||||
sizeof(struct sta_rec_ht) + \
|
||||
sizeof(struct sta_rec_vht) + \
|
||||
sizeof(struct sta_rec_uapsd) + \
|
||||
sizeof(struct tlv) + \
|
||||
MT7615_WTBL_UPDATE_MAX_SIZE)
|
||||
|
||||
#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
|
||||
sizeof(struct wtbl_ba))
|
||||
|
||||
enum {
|
||||
CH_SWITCH_NORMAL = 0,
|
||||
CH_SWITCH_SCAN = 3,
|
||||
|
@ -1,3 +1,6 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -133,11 +133,11 @@ struct mt7615_vif {
|
||||
};
|
||||
|
||||
struct mib_stats {
|
||||
u16 ack_fail_cnt;
|
||||
u16 fcs_err_cnt;
|
||||
u16 rts_cnt;
|
||||
u16 rts_retries_cnt;
|
||||
u16 ba_miss_cnt;
|
||||
u32 ack_fail_cnt;
|
||||
u32 fcs_err_cnt;
|
||||
u32 rts_cnt;
|
||||
u32 rts_retries_cnt;
|
||||
u32 ba_miss_cnt;
|
||||
unsigned long aggr_per;
|
||||
};
|
||||
|
||||
@ -168,7 +168,7 @@ struct mt7615_phy {
|
||||
u8 rdd_state;
|
||||
int dfs_state;
|
||||
|
||||
__le32 rx_ampdu_ts;
|
||||
u32 rx_ampdu_ts;
|
||||
u32 ampdu_ref;
|
||||
|
||||
struct mib_stats mib;
|
||||
@ -376,6 +376,7 @@ int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,
|
||||
enum nl80211_band band);
|
||||
int mt7615_wait_pdma_busy(struct mt7615_dev *dev);
|
||||
int mt7615_dma_init(struct mt7615_dev *dev);
|
||||
void mt7615_dma_start(struct mt7615_dev *dev);
|
||||
void mt7615_dma_cleanup(struct mt7615_dev *dev);
|
||||
int mt7615_mcu_init(struct mt7615_dev *dev);
|
||||
bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);
|
||||
@ -408,11 +409,6 @@ static inline bool is_mt7615(struct mt76_dev *dev)
|
||||
return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611;
|
||||
}
|
||||
|
||||
static inline bool is_mt7663(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7663;
|
||||
}
|
||||
|
||||
static inline bool is_mt7611(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7611;
|
||||
@ -524,6 +520,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
void mt7615_mac_work(struct work_struct *work);
|
||||
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
|
||||
struct mt76_txwi_cache *txwi);
|
||||
int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
|
||||
int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
|
||||
int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
|
||||
const struct mt7615_dfs_pulse *pulse);
|
||||
@ -557,6 +557,8 @@ u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset);
|
||||
void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
|
||||
void mt7615_coredump_work(struct work_struct *work);
|
||||
|
||||
void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en);
|
||||
|
||||
/* usb */
|
||||
int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
|
@ -13,9 +13,9 @@
|
||||
#include "mcu.h"
|
||||
|
||||
static const struct pci_device_id mt7615_pci_device_table[] = {
|
||||
{ PCI_DEVICE(0x14c3, 0x7615) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7663) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7611) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7615) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7663) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7611) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -126,6 +126,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
|
||||
int ret;
|
||||
|
||||
mt7615_init_device(dev);
|
||||
INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
|
||||
|
||||
/* init led callbacks */
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||
|
@ -181,3 +181,171 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt7615_dma_reset(struct mt7615_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
|
||||
mt7615_dma_start(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_dma_reset);
|
||||
|
||||
static void
|
||||
mt7615_hif_int_event_trigger(struct mt7615_dev *dev, u8 event)
|
||||
{
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, event);
|
||||
|
||||
mt7622_trigger_hif_int(dev, true);
|
||||
mt7622_trigger_hif_int(dev, false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
ret = wait_event_timeout(dev->reset_wait,
|
||||
(READ_ONCE(dev->reset_state) & state),
|
||||
MT7615_RESET_TIMEOUT);
|
||||
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv;
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
mt7615_mcu_add_beacon(dev, hw, vif,
|
||||
vif->bss_conf.enable_beacon);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_update_beacons(struct mt7615_dev *dev)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_update_vif_beacon, dev->mt76.hw);
|
||||
|
||||
if (!dev->mt76.phy2)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7615_update_vif_beacon, dev->mt76.phy2->hw);
|
||||
}
|
||||
|
||||
void mt7615_mac_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7615_phy *phy2;
|
||||
struct mt76_phy *ext_phy;
|
||||
struct mt7615_dev *dev;
|
||||
|
||||
dev = container_of(work, struct mt7615_dev, reset_work);
|
||||
ext_phy = dev->mt76.phy2;
|
||||
phy2 = ext_phy ? ext_phy->priv : NULL;
|
||||
|
||||
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
|
||||
return;
|
||||
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
if (ext_phy)
|
||||
ieee80211_stop_queues(ext_phy->hw);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
del_timer_sync(&dev->phy.roc_timer);
|
||||
cancel_work_sync(&dev->phy.roc_work);
|
||||
if (phy2) {
|
||||
set_bit(MT76_RESET, &phy2->mt76->state);
|
||||
cancel_delayed_work_sync(&phy2->mt76->mac_work);
|
||||
del_timer_sync(&phy2->roc_timer);
|
||||
cancel_work_sync(&phy2->roc_work);
|
||||
}
|
||||
|
||||
/* lock/unlock all queues to ensure that no tx is pending */
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
if (ext_phy)
|
||||
mt76_txq_schedule_all(ext_phy);
|
||||
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
napi_disable(&dev->mt76.napi[0]);
|
||||
napi_disable(&dev->mt76.napi[1]);
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mt7615_mutex_acquire(dev);
|
||||
|
||||
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_STOPPED);
|
||||
|
||||
mt7615_tx_token_put(dev);
|
||||
idr_init(&dev->token);
|
||||
|
||||
if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
|
||||
mt7615_dma_reset(dev);
|
||||
|
||||
mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0);
|
||||
|
||||
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_INIT);
|
||||
mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
|
||||
}
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
if (phy2)
|
||||
clear_bit(MT76_RESET, &phy2->mt76->state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
|
||||
napi_enable(&dev->mt76.napi[0]);
|
||||
napi_schedule(&dev->mt76.napi[0]);
|
||||
|
||||
napi_enable(&dev->mt76.napi[1]);
|
||||
napi_schedule(&dev->mt76.napi[1]);
|
||||
|
||||
ieee80211_wake_queues(mt76_hw(dev));
|
||||
if (ext_phy)
|
||||
ieee80211_wake_queues(ext_phy->hw);
|
||||
|
||||
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE);
|
||||
mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
|
||||
|
||||
mt7615_update_beacons(dev);
|
||||
|
||||
mt7615_mutex_release(dev);
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
|
||||
MT7615_WATCHDOG_TIME);
|
||||
if (phy2)
|
||||
ieee80211_queue_delayed_work(ext_phy->hw,
|
||||
&phy2->mt76->mac_work,
|
||||
MT7615_WATCHDOG_TIME);
|
||||
|
||||
}
|
||||
|
@ -368,7 +368,9 @@ enum mt7615_reg_base {
|
||||
|
||||
#define MT_DMA_DCR0 MT_WF_DMA(0x000)
|
||||
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2)
|
||||
#define MT_DMA_DCR0_DAMSDU_EN BIT(16)
|
||||
#define MT_DMA_DCR0_RX_VEC_DROP BIT(17)
|
||||
#define MT_DMA_DCR0_RX_HDR_TRANS_EN BIT(19)
|
||||
|
||||
#define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40)
|
||||
#define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2)
|
||||
@ -447,9 +449,10 @@ enum mt7615_reg_base {
|
||||
|
||||
#define MT_LPON(_n) ((dev)->reg_map[MT_LPON_BASE] + (_n))
|
||||
|
||||
#define MT_LPON_T0CR MT_LPON(0x010)
|
||||
#define MT_LPON_T0CR_MODE GENMASK(1, 0)
|
||||
#define MT_LPON_T0CR_WRITE BIT(0)
|
||||
#define MT_LPON_TCR0(_n) MT_LPON(0x010 + ((_n) * 4))
|
||||
#define MT_LPON_TCR2(_n) MT_LPON(0x0f8 + ((_n) - 2) * 4)
|
||||
#define MT_LPON_TCR_MODE GENMASK(1, 0)
|
||||
#define MT_LPON_TCR_WRITE BIT(0)
|
||||
|
||||
#define MT_LPON_UTTR0 MT_LPON(0x018)
|
||||
#define MT_LPON_UTTR1 MT_LPON(0x01c)
|
||||
|
@ -218,12 +218,15 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0;
|
||||
bool mcu = q == dev->q_mcu[MT_MCUQ_WM];
|
||||
struct mt76_sdio *sdio = &dev->sdio;
|
||||
u8 pad;
|
||||
|
||||
qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid;
|
||||
while (q->first != q->head) {
|
||||
struct mt76_queue_entry *e = &q->entry[q->first];
|
||||
struct sk_buff *iter;
|
||||
|
||||
smp_rmb();
|
||||
|
||||
if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) {
|
||||
__skb_put_zero(e->skb, 4);
|
||||
err = __mt7663s_xmit_queue(dev, e->skb->data,
|
||||
@ -234,7 +237,8 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ)
|
||||
pad = roundup(e->skb->len, 4) - e->skb->len;
|
||||
if (len + e->skb->len + pad + 4 > MT76S_XMIT_BUF_SZ)
|
||||
break;
|
||||
|
||||
if (mt7663s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz,
|
||||
@ -252,6 +256,11 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
len += iter->len;
|
||||
nframes++;
|
||||
}
|
||||
|
||||
if (unlikely(pad)) {
|
||||
memset(sdio->xmit_buf[qid] + len, 0, pad);
|
||||
len += pad;
|
||||
}
|
||||
next:
|
||||
q->first = (q->first + 1) % q->ndesc;
|
||||
e->done = true;
|
||||
|
@ -67,6 +67,7 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
|
||||
struct mt7615_rate_desc *rate = &wrd->rate;
|
||||
struct mt7615_sta *sta = wrd->sta;
|
||||
u32 w5, w27, addr, val;
|
||||
u16 idx = sta->vif->mt76.omac_idx;
|
||||
|
||||
lockdep_assert_held(&dev->mt76.mutex);
|
||||
|
||||
@ -118,7 +119,10 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
|
||||
|
||||
sta->rate_probe = sta->rateset[rate->rateset].probe_rate.idx != -1;
|
||||
|
||||
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */
|
||||
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
|
||||
addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
|
||||
|
||||
mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
|
||||
val = mt76_rr(dev, MT_LPON_UTTR0);
|
||||
sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset;
|
||||
|
||||
|
@ -73,6 +73,11 @@ static inline bool is_mt7921(struct mt76_dev *dev)
|
||||
return mt76_chip(dev) == 0x7961;
|
||||
}
|
||||
|
||||
static inline bool is_mt7663(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7663;
|
||||
}
|
||||
|
||||
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
|
||||
void mt76_connac_power_save_sched(struct mt76_phy *phy,
|
||||
struct mt76_connac_pm *pm);
|
||||
|
@ -287,7 +287,7 @@ mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
&hdr.wlan_idx_hi);
|
||||
if (!nskb) {
|
||||
nskb = mt76_mcu_msg_alloc(dev, NULL,
|
||||
MT76_CONNAC_WTBL_UPDATE_BA_SIZE);
|
||||
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE);
|
||||
if (!nskb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -392,6 +392,21 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
uapsd->max_sp = sta->max_sp;
|
||||
}
|
||||
|
||||
void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid,
|
||||
void *sta_wtbl, void *wtbl_tlv)
|
||||
{
|
||||
struct wtbl_hdr_trans *htr;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS,
|
||||
sizeof(*htr),
|
||||
wtbl_tlv, sta_wtbl);
|
||||
htr = (struct wtbl_hdr_trans *)tlv;
|
||||
htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);
|
||||
|
||||
void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
@ -655,7 +670,8 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
|
||||
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif,
|
||||
u8 rcpi)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &mphy->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
@ -704,6 +720,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
phy = (struct sta_rec_phy *)tlv;
|
||||
phy->phy_type = mt76_connac_get_phy_mode_v2(mphy, vif, band, sta);
|
||||
phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates);
|
||||
phy->rcpi = rcpi;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info));
|
||||
ra_info = (struct sta_rec_ra_info *)tlv;
|
||||
@ -808,40 +825,42 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv);
|
||||
|
||||
int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid,
|
||||
bool enable, int cmd)
|
||||
struct mt76_sta_cmd_info *info)
|
||||
{
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct wtbl_req_hdr *wtbl_hdr;
|
||||
struct tlv *sta_wtbl;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);
|
||||
skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable);
|
||||
if (enable && sta)
|
||||
mt76_connac_mcu_sta_tlv(phy, skb, sta, vif);
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, info->enable);
|
||||
if (info->enable && info->sta)
|
||||
mt76_connac_mcu_sta_tlv(phy, skb, info->sta, info->vif,
|
||||
info->rcpi);
|
||||
|
||||
sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
|
||||
sizeof(struct tlv));
|
||||
|
||||
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid,
|
||||
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid,
|
||||
WTBL_RESET_AND_SET,
|
||||
sta_wtbl, &skb);
|
||||
if (enable) {
|
||||
mt76_connac_mcu_wtbl_generic_tlv(dev, skb, vif, sta, sta_wtbl,
|
||||
wtbl_hdr);
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, sta, sta_wtbl,
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
if (info->enable) {
|
||||
mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,
|
||||
info->sta, sta_wtbl,
|
||||
wtbl_hdr);
|
||||
if (info->sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
|
||||
sta_wtbl, wtbl_hdr);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
|
||||
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_sta_cmd);
|
||||
|
||||
@ -946,6 +965,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_AP:
|
||||
basic_req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP);
|
||||
break;
|
||||
@ -1195,6 +1215,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
|
||||
.center_chan = ieee80211_frequency_to_channel(freq1),
|
||||
.center_chan2 = ieee80211_frequency_to_channel(freq2),
|
||||
.tx_streams = hweight8(phy->antenna_mask),
|
||||
.ht_op_info = 4, /* set HT 40M allowed */
|
||||
.rx_streams = phy->chainmask,
|
||||
.short_st = true,
|
||||
},
|
||||
@ -1287,6 +1308,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
default:
|
||||
rlm_req.rlm.bw = CMD_CBW_20MHZ;
|
||||
rlm_req.rlm.ht_op_info = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1306,7 +1328,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct cfg80211_scan_request *sreq = &scan_req->req;
|
||||
int n_ssids = 0, err, i, duration = MT76_CONNAC_SCAN_CHANNEL_TIME;
|
||||
int n_ssids = 0, err, i, duration;
|
||||
int ext_channels_num = max_t(int, sreq->n_channels - 32, 0);
|
||||
struct ieee80211_channel **scan_list = sreq->channels;
|
||||
struct mt76_dev *mdev = phy->dev;
|
||||
@ -1343,6 +1365,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
req->ssid_type_ext = n_ssids ? BIT(0) : 0;
|
||||
req->ssids_num = n_ssids;
|
||||
|
||||
duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
|
||||
/* increase channel time for passive scan */
|
||||
if (!sreq->n_ssids)
|
||||
duration *= 2;
|
||||
@ -1368,11 +1391,14 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
req->ies_len = cpu_to_le16(sreq->ie_len);
|
||||
}
|
||||
|
||||
if (is_mt7921(phy->dev))
|
||||
req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
|
||||
|
||||
memcpy(req->bssid, sreq->bssid, ETH_ALEN);
|
||||
if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
get_random_mask_addr(req->random_mac, sreq->mac_addr,
|
||||
sreq->mac_addr_mask);
|
||||
req->scan_func = 1;
|
||||
req->scan_func |= SCAN_FUNC_RANDOM_MAC;
|
||||
}
|
||||
|
||||
err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CMD_START_HW_SCAN, false);
|
||||
@ -1433,10 +1459,13 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
|
||||
req->version = 1;
|
||||
req->seq_num = mvif->scan_seq_num | ext_phy << 7;
|
||||
|
||||
if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
get_random_mask_addr(req->random_mac, sreq->mac_addr,
|
||||
if (is_mt7663(phy->dev) &&
|
||||
(sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) {
|
||||
get_random_mask_addr(req->mt7663.random_mac, sreq->mac_addr,
|
||||
sreq->mac_addr_mask);
|
||||
req->scan_func = 1;
|
||||
} else if (is_mt7921(phy->dev)) {
|
||||
req->mt7921.bss_idx = mvif->idx;
|
||||
}
|
||||
|
||||
req->ssids_num = sreq->n_ssids;
|
||||
|
@ -210,7 +210,7 @@ struct wtbl_hdr_trans {
|
||||
__le16 len;
|
||||
u8 to_ds;
|
||||
u8 from_ds;
|
||||
u8 disable_rx_trans;
|
||||
u8 no_rx_trans;
|
||||
u8 rsv;
|
||||
} __packed;
|
||||
|
||||
@ -304,9 +304,6 @@ struct wtbl_raw {
|
||||
sizeof(struct tlv) + \
|
||||
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
|
||||
|
||||
#define MT76_CONNAC_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
|
||||
sizeof(struct wtbl_ba))
|
||||
|
||||
enum {
|
||||
STA_REC_BASIC,
|
||||
STA_REC_RA,
|
||||
@ -365,6 +362,9 @@ enum {
|
||||
#define NETWORK_IBSS BIT(18)
|
||||
#define NETWORK_WDS BIT(21)
|
||||
|
||||
#define SCAN_FUNC_RANDOM_MAC BIT(0)
|
||||
#define SCAN_FUNC_SPLIT_SCAN BIT(5)
|
||||
|
||||
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
|
||||
#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
|
||||
#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
|
||||
@ -759,11 +759,19 @@ struct mt76_connac_sched_scan_req {
|
||||
u8 channel_type;
|
||||
u8 channels_num;
|
||||
u8 intervals_num;
|
||||
u8 scan_func; /* BIT(0) eable random mac address */
|
||||
u8 scan_func; /* MT7663: BIT(0) eable random mac address */
|
||||
struct mt76_connac_mcu_scan_channel channels[64];
|
||||
__le16 intervals[MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL];
|
||||
u8 random_mac[ETH_ALEN]; /* valid when BIT(0) in scan_func is set */
|
||||
union {
|
||||
struct {
|
||||
u8 random_mac[ETH_ALEN];
|
||||
u8 pad2[58];
|
||||
} mt7663;
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad2[63];
|
||||
} mt7921;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_sched_scan_done {
|
||||
@ -876,6 +884,17 @@ struct mt76_connac_suspend_tlv {
|
||||
u8 pad[5];
|
||||
} __packed;
|
||||
|
||||
struct mt76_sta_cmd_info {
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
bool enable;
|
||||
int cmd;
|
||||
u8 rcpi;
|
||||
};
|
||||
|
||||
#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
|
||||
#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
|
||||
|
||||
@ -917,9 +936,13 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, void *sta_wtbl,
|
||||
void *wtbl_tlv);
|
||||
void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
|
||||
struct mt76_wcid *wcid,
|
||||
void *sta_wtbl, void *wtbl_tlv);
|
||||
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif);
|
||||
struct ieee80211_vif *vif,
|
||||
u8 rcpi);
|
||||
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, void *sta_wtbl,
|
||||
void *wtbl_tlv);
|
||||
@ -942,10 +965,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
|
||||
struct mt76_wcid *wcid,
|
||||
bool enable);
|
||||
int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid,
|
||||
bool enable, int cmd);
|
||||
struct mt76_sta_cmd_info *info);
|
||||
void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif);
|
||||
int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band);
|
||||
|
@ -221,9 +221,9 @@ mt76x0e_remove(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
static const struct pci_device_id mt76x0e_device_table[] = {
|
||||
{ PCI_DEVICE(0x14c3, 0x7610) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7630) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7650) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7610) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7630) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7650) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,8 @@ static struct usb_device_id mt76x0_device_table[] = {
|
||||
{ USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH */
|
||||
{ USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
|
||||
{ USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac Stick */
|
||||
{ USB_DEVICE(0x2357, 0x0123) }, /* TP-LINK T2UHP */
|
||||
{ USB_DEVICE(0x2357, 0x0123) }, /* TP-LINK T2UHP_US_v1 */
|
||||
{ USB_DEVICE(0x2357, 0x010b) }, /* TP-LINK T2UHP_UN_v1 */
|
||||
/* TP-LINK Archer T1U */
|
||||
{ USB_DEVICE(0x2357, 0x0105), .driver_info = 1, },
|
||||
/* MT7630U */
|
||||
|
@ -770,6 +770,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
|
||||
void *rxi)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct mt76x02_rxwi *rxwi = rxi;
|
||||
struct mt76x02_sta *sta;
|
||||
u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
|
||||
@ -864,7 +865,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
|
||||
status->freq = dev->mphy.chandef.chan->center_freq;
|
||||
status->band = dev->mphy.chandef.chan->band;
|
||||
|
||||
status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
|
||||
status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
|
||||
|
||||
return mt76x02_mac_process_rate(dev, status, rate);
|
||||
|
@ -230,7 +230,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt76x02_poll_tx, NAPI_POLL_WEIGHT);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
|
@ -447,6 +447,10 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* MT76x0 GTK offloading does not work with more than one VIF */
|
||||
if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
|
||||
wcid = msta ? &msta->wcid : &mvif->group_wcid;
|
||||
|
||||
|
@ -10,9 +10,9 @@
|
||||
#include "mt76x2.h"
|
||||
|
||||
static const struct pci_device_id mt76x2e_device_table[] = {
|
||||
{ PCI_DEVICE(0x14c3, 0x7662) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7612) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7602) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7662) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7612) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7602) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,6 @@
|
||||
obj-$(CONFIG_MT7915E) += mt7915e.o
|
||||
|
||||
mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
|
||||
debugfs.o
|
||||
debugfs.o mmio.o
|
||||
|
||||
mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
|
@ -124,7 +124,7 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
|
||||
range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bound); i++)
|
||||
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1;
|
||||
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
|
||||
|
||||
seq_printf(file, "\nPhy %d\n", ext_phy);
|
||||
|
||||
|
@ -110,121 +110,13 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev)
|
||||
__mt7915_dma_prefetch(dev, MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE);
|
||||
}
|
||||
|
||||
static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
static const struct {
|
||||
u32 phys;
|
||||
u32 mapped;
|
||||
u32 size;
|
||||
} fixed_map[] = {
|
||||
{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
|
||||
{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
|
||||
{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
|
||||
{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
|
||||
{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
|
||||
{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
|
||||
{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
|
||||
{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
|
||||
{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
|
||||
{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
|
||||
{ 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
|
||||
{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
|
||||
{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
|
||||
{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
|
||||
{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
|
||||
{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
|
||||
{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
|
||||
{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
|
||||
{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
|
||||
{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
|
||||
{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
|
||||
{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
|
||||
{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
|
||||
{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
|
||||
{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
|
||||
{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
|
||||
{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
|
||||
{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
|
||||
{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
|
||||
{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
|
||||
{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
|
||||
{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
|
||||
{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
|
||||
{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
|
||||
{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
|
||||
{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
|
||||
{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
|
||||
{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
|
||||
};
|
||||
int i;
|
||||
|
||||
if (addr < 0x100000)
|
||||
return addr;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
|
||||
u32 ofs;
|
||||
|
||||
if (addr < fixed_map[i].phys)
|
||||
continue;
|
||||
|
||||
ofs = addr - fixed_map[i].phys;
|
||||
if (ofs > fixed_map[i].size)
|
||||
continue;
|
||||
|
||||
return fixed_map[i].mapped + ofs;
|
||||
}
|
||||
|
||||
if ((addr >= 0x18000000 && addr < 0x18c00000) ||
|
||||
(addr >= 0x70000000 && addr < 0x78000000) ||
|
||||
(addr >= 0x7c000000 && addr < 0x7c400000))
|
||||
return mt7915_reg_map_l1(dev, addr);
|
||||
|
||||
return mt7915_reg_map_l2(dev, addr);
|
||||
}
|
||||
|
||||
static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
u32 addr = __mt7915_reg_addr(dev, offset);
|
||||
|
||||
return dev->bus_ops->rr(mdev, addr);
|
||||
}
|
||||
|
||||
static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
u32 addr = __mt7915_reg_addr(dev, offset);
|
||||
|
||||
dev->bus_ops->wr(mdev, addr, val);
|
||||
}
|
||||
|
||||
static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
u32 addr = __mt7915_reg_addr(dev, offset);
|
||||
|
||||
return dev->bus_ops->rmw(mdev, addr, mask, val);
|
||||
}
|
||||
|
||||
int mt7915_dma_init(struct mt7915_dev *dev)
|
||||
{
|
||||
/* Increase buffer size to receive large VHT/HE MPDUs */
|
||||
struct mt76_bus_ops *bus_ops;
|
||||
int rx_buf_size = MT_RX_BUF_SIZE * 2;
|
||||
u32 hif1_ofs = 0;
|
||||
int ret;
|
||||
|
||||
dev->bus_ops = dev->mt76.bus;
|
||||
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
|
||||
GFP_KERNEL);
|
||||
if (!bus_ops)
|
||||
return -ENOMEM;
|
||||
|
||||
bus_ops->rr = mt7915_rr;
|
||||
bus_ops->wr = mt7915_wr;
|
||||
bus_ops->rmw = mt7915_rmw;
|
||||
dev->mt76.bus = bus_ops;
|
||||
|
||||
mt76_dma_attach(&dev->mt76);
|
||||
|
||||
if (dev->hif2)
|
||||
@ -325,7 +217,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7915_poll_tx, NAPI_POLL_WEIGHT);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
|
@ -124,7 +124,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
u8 chain_idx)
|
||||
{
|
||||
int index;
|
||||
int index, target_power;
|
||||
bool tssi_on;
|
||||
|
||||
if (chain_idx > 3)
|
||||
@ -133,15 +133,22 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
||||
tssi_on = mt7915_tssi_enabled(dev, chan->band);
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ) {
|
||||
index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on;
|
||||
} else {
|
||||
int group = tssi_on ?
|
||||
mt7915_get_channel_group(chan->hw_value) : 8;
|
||||
index = MT_EE_TX0_POWER_2G + chain_idx * 3;
|
||||
target_power = mt7915_eeprom_read(dev, index);
|
||||
|
||||
index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group;
|
||||
if (!tssi_on)
|
||||
target_power += mt7915_eeprom_read(dev, index + 1);
|
||||
} else {
|
||||
int group = mt7915_get_channel_group(chan->hw_value);
|
||||
|
||||
index = MT_EE_TX0_POWER_5G + chain_idx * 12;
|
||||
target_power = mt7915_eeprom_read(dev, index + group);
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += mt7915_eeprom_read(dev, index + 8);
|
||||
}
|
||||
|
||||
return mt7915_eeprom_read(dev, index);
|
||||
return target_power;
|
||||
}
|
||||
|
||||
static const u8 sku_cck_delta_map[] = {
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include "mt7915.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
#define CCK_RATE(_idx, _rate) { \
|
||||
@ -93,6 +94,10 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
||||
hw->queues = 4;
|
||||
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
|
||||
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
|
||||
hw->netdev_features = NETIF_F_RXCSUM;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||
|
||||
phy->slottime = 9;
|
||||
|
||||
@ -108,9 +113,28 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
||||
|
||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
|
||||
if (phy->mt76->cap.has_2ghz)
|
||||
phy->mt76->sband_2g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
phy->mt76->sband_5g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
}
|
||||
|
||||
mt76_set_stream_caps(phy->mt76, true);
|
||||
mt7915_set_stream_vht_txbf_caps(phy);
|
||||
mt7915_set_stream_he_caps(phy);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -153,16 +177,14 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
|
||||
int i;
|
||||
|
||||
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
|
||||
/* disable hardware de-agg */
|
||||
mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
|
||||
/* enable hardware de-agg */
|
||||
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
|
||||
|
||||
for (i = 0; i < MT7915_WTBL_SIZE; i++)
|
||||
mt7915_mac_wtbl_update(dev, i,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
for (i = 0; i < 2; i++)
|
||||
mt7915_mac_init_band(dev, i);
|
||||
|
||||
mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b);
|
||||
}
|
||||
|
||||
static int mt7915_txbf_init(struct mt7915_dev *dev)
|
||||
@ -238,22 +260,17 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
|
||||
phy->mt76 = mphy;
|
||||
mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask;
|
||||
mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;
|
||||
mt7915_init_wiphy(mphy->hw);
|
||||
|
||||
INIT_LIST_HEAD(&phy->stats_list);
|
||||
INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
|
||||
|
||||
mt7915_eeprom_parse_band_config(phy);
|
||||
mt7915_set_stream_vht_txbf_caps(phy);
|
||||
mt7915_set_stream_he_caps(phy);
|
||||
mt7915_init_wiphy(mphy->hw);
|
||||
|
||||
memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,
|
||||
ETH_ALEN);
|
||||
mt76_eeprom_override(mphy);
|
||||
|
||||
/* The second interface does not get any packets unless it has a vif */
|
||||
ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF);
|
||||
|
||||
ret = mt7915_init_tx_queues(phy, MT7915_TXQ_BAND1,
|
||||
MT7915_TX_RING_SIZE);
|
||||
if (ret)
|
||||
@ -280,7 +297,45 @@ static void mt7915_init_work(struct work_struct *work)
|
||||
mt7915_mac_init(dev);
|
||||
mt7915_init_txpower(dev);
|
||||
mt7915_txbf_init(dev);
|
||||
mt7915_register_ext_phy(dev);
|
||||
}
|
||||
|
||||
static void mt7915_wfsys_reset(struct mt7915_dev *dev)
|
||||
{
|
||||
u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;
|
||||
|
||||
#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0)
|
||||
#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16)
|
||||
|
||||
mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);
|
||||
|
||||
/* change to software control */
|
||||
val |= MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
/* reset wfsys */
|
||||
val &= ~MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
/* release wfsys then mcu re-excutes romcode */
|
||||
val |= MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
/* switch to hw control */
|
||||
val &= ~MT_TOP_PWR_SW_RST;
|
||||
val |= MT_TOP_PWR_HW_CTRL;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
/* check whether mcu resets to default */
|
||||
if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT,
|
||||
MT_MCU_DUMMY_DEFAULT, 1000)) {
|
||||
dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* wfsys reset won't clear host registers */
|
||||
mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
static int mt7915_init_hardware(struct mt7915_dev *dev)
|
||||
@ -293,7 +348,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
|
||||
spin_lock_init(&dev->token_lock);
|
||||
idr_init(&dev->token);
|
||||
|
||||
dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5));
|
||||
dev->dbdc_support = !!(mt76_rr(dev, MT_HW_BOUND) & BIT(5));
|
||||
|
||||
/* If MCU was already running, it is likely in a bad state */
|
||||
if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) >
|
||||
FW_STATE_FW_DOWNLOAD)
|
||||
mt7915_wfsys_reset(dev);
|
||||
|
||||
ret = mt7915_dma_init(dev);
|
||||
if (ret)
|
||||
@ -307,9 +367,15 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
|
||||
*/
|
||||
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
|
||||
|
||||
ret = mt7915_mcu_init(dev);
|
||||
if (ret) {
|
||||
/* Reset and try again */
|
||||
mt7915_wfsys_reset(dev);
|
||||
|
||||
ret = mt7915_mcu_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt7915_eeprom_init(dev);
|
||||
if (ret < 0)
|
||||
@ -330,8 +396,14 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
|
||||
|
||||
void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
|
||||
{
|
||||
int nss = hweight8(phy->mt76->chainmask);
|
||||
u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap;
|
||||
int nss;
|
||||
u32 *cap;
|
||||
|
||||
if (!phy->mt76->cap.has_5ghz)
|
||||
return;
|
||||
|
||||
nss = hweight8(phy->mt76->chainmask);
|
||||
cap = &phy->mt76->sband_5g.sband.vht_cap.cap;
|
||||
|
||||
*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
||||
@ -635,25 +707,14 @@ int mt7915_register_device(struct mt7915_dev *dev)
|
||||
return ret;
|
||||
|
||||
mt7915_init_wiphy(hw);
|
||||
dev->mphy.sband_2g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
dev->mphy.sband_5g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
|
||||
if (!dev->dbdc_support)
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
|
||||
|
||||
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
|
||||
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
|
||||
|
||||
mt76_set_stream_caps(&dev->mphy, true);
|
||||
mt7915_set_stream_vht_txbf_caps(&dev->phy);
|
||||
mt7915_set_stream_he_caps(&dev->phy);
|
||||
dev->phy.dfs_state = -1;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
@ -667,6 +728,10 @@ int mt7915_register_device(struct mt7915_dev *dev)
|
||||
|
||||
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
|
||||
|
||||
ret = mt7915_register_ext_phy(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7915_init_debugfs(dev);
|
||||
}
|
||||
|
||||
|
@ -317,11 +317,18 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
__le32 *rxd = (__le32 *)skb->data;
|
||||
__le32 *rxv = NULL;
|
||||
u32 mode = 0;
|
||||
u32 rxd0 = le32_to_cpu(rxd[0]);
|
||||
u32 rxd1 = le32_to_cpu(rxd[1]);
|
||||
u32 rxd2 = le32_to_cpu(rxd[2]);
|
||||
u32 rxd3 = le32_to_cpu(rxd[3]);
|
||||
u32 rxd4 = le32_to_cpu(rxd[4]);
|
||||
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
|
||||
bool unicast, insert_ccmp_hdr = false;
|
||||
u8 remove_pad;
|
||||
u8 remove_pad, amsdu_info;
|
||||
bool hdr_trans;
|
||||
u16 seq_ctrl = 0;
|
||||
u8 qos_ctl = 0;
|
||||
__le16 fc = 0;
|
||||
int i, idx;
|
||||
|
||||
memset(status, 0, sizeof(*status));
|
||||
@ -338,8 +345,12 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
if (!test_bit(MT76_STATE_RUNNING, &mphy->state))
|
||||
return -EINVAL;
|
||||
|
||||
if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
|
||||
return -EINVAL;
|
||||
|
||||
unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
|
||||
idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
|
||||
hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
|
||||
status->wcid = mt7915_rx_get_wcid(dev, idx, unicast);
|
||||
|
||||
if (status->wcid) {
|
||||
@ -362,6 +373,9 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
if (!sband->channels)
|
||||
return -EINVAL;
|
||||
|
||||
if ((rxd0 & csum_mask) == csum_mask)
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
if (rxd1 & MT_RXD1_NORMAL_FCS_ERR)
|
||||
status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
@ -375,19 +389,6 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
|
||||
}
|
||||
|
||||
if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (phy->rx_ampdu_ts != rxd[14]) {
|
||||
if (!++phy->ampdu_ref)
|
||||
phy->ampdu_ref++;
|
||||
}
|
||||
phy->rx_ampdu_ts = rxd[14];
|
||||
|
||||
status->ampdu_ref = phy->ampdu_ref;
|
||||
}
|
||||
|
||||
remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2);
|
||||
|
||||
if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
|
||||
@ -395,6 +396,13 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
rxd += 6;
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_4) {
|
||||
u32 v0 = le32_to_cpu(rxd[0]);
|
||||
u32 v2 = le32_to_cpu(rxd[2]);
|
||||
|
||||
fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0));
|
||||
qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2);
|
||||
seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2);
|
||||
|
||||
rxd += 4;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
@ -419,6 +427,22 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_2) {
|
||||
status->timestamp = le32_to_cpu(rxd[0]);
|
||||
status->flag |= RX_FLAG_MACTIME_START;
|
||||
|
||||
if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (phy->rx_ampdu_ts != status->timestamp) {
|
||||
if (!++phy->ampdu_ref)
|
||||
phy->ampdu_ref++;
|
||||
}
|
||||
phy->rx_ampdu_ts = status->timestamp;
|
||||
|
||||
status->ampdu_ref = phy->ampdu_ref;
|
||||
}
|
||||
|
||||
rxd += 2;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
@ -541,23 +565,47 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
|
||||
|
||||
if (insert_ccmp_hdr) {
|
||||
amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4);
|
||||
status->amsdu = !!amsdu_info;
|
||||
if (status->amsdu) {
|
||||
status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
|
||||
status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
|
||||
if (!hdr_trans) {
|
||||
memmove(skb->data + 2, skb->data,
|
||||
ieee80211_get_hdrlen_from_skb(skb));
|
||||
skb_pull(skb, 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (insert_ccmp_hdr && !hdr_trans) {
|
||||
u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
|
||||
|
||||
mt76_insert_ccmp_hdr(skb, key_id);
|
||||
}
|
||||
|
||||
if (!hdr_trans) {
|
||||
hdr = mt76_skb_get_hdr(skb);
|
||||
fc = hdr->frame_control;
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
|
||||
qos_ctl = *ieee80211_get_qos_ctl(hdr);
|
||||
}
|
||||
} else {
|
||||
status->flag &= ~(RX_FLAG_RADIOTAP_HE |
|
||||
RX_FLAG_RADIOTAP_HE_MU);
|
||||
status->flag |= RX_FLAG_8023;
|
||||
}
|
||||
|
||||
if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
|
||||
mt7915_mac_decode_he_radiotap(skb, status, rxv, mode);
|
||||
|
||||
hdr = mt76_skb_get_hdr(skb);
|
||||
if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
|
||||
if (!status->wcid || !ieee80211_is_data_qos(fc))
|
||||
return 0;
|
||||
|
||||
status->aggr = unicast &&
|
||||
!ieee80211_is_qos_nullfunc(hdr->frame_control);
|
||||
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
|
||||
!ieee80211_is_qos_nullfunc(fc);
|
||||
status->qos_ctl = qos_ctl;
|
||||
status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1091,7 +1139,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev,
|
||||
int i;
|
||||
|
||||
txp = mt7915_txwi_to_txp(dev, t);
|
||||
for (i = 1; i < txp->nbuf; i++)
|
||||
for (i = 0; i < txp->nbuf; i++)
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
|
||||
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
|
||||
}
|
||||
@ -1252,8 +1300,8 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy)
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
u32 reg = MT_WF_PHY_RX_CTRL1(ext_phy);
|
||||
|
||||
mt7915_l2_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN);
|
||||
mt7915_l2_set(dev, reg, BIT(11) | BIT(9));
|
||||
mt76_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN);
|
||||
mt76_set(dev, reg, BIT(11) | BIT(9));
|
||||
}
|
||||
|
||||
void mt7915_mac_reset_counters(struct mt7915_phy *phy)
|
||||
@ -1346,11 +1394,11 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
||||
|
||||
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy)
|
||||
{
|
||||
mt7915_l2_set(dev, MT_WF_PHY_RXTD12(ext_phy),
|
||||
mt76_set(dev, MT_WF_PHY_RXTD12(ext_phy),
|
||||
MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY |
|
||||
MT_WF_PHY_RXTD12_IRPI_SW_CLR);
|
||||
|
||||
mt7915_l2_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy),
|
||||
mt76_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy),
|
||||
FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5));
|
||||
}
|
||||
|
||||
@ -1366,7 +1414,7 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
|
||||
u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {
|
||||
val = mt7915_l2_rr(dev, reg);
|
||||
val = mt76_rr(dev, reg);
|
||||
sum += val * nf_power[i];
|
||||
n += val;
|
||||
}
|
||||
@ -1470,9 +1518,8 @@ mt7915_update_beacons(struct mt7915_dev *dev)
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_dma_reset(struct mt7915_phy *phy)
|
||||
mt7915_dma_reset(struct mt7915_dev *dev)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
struct mt76_phy *mphy_ext = dev->mt76.phy2;
|
||||
u32 hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE;
|
||||
int i;
|
||||
@ -1489,18 +1536,20 @@ mt7915_dma_reset(struct mt7915_phy *phy)
|
||||
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA1_GLO_CFG_RX_DMA_EN));
|
||||
}
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true);
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++) {
|
||||
mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true);
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
if (mphy_ext)
|
||||
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
|
||||
}
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
}
|
||||
|
||||
/* re-init prefetch settings after reset */
|
||||
mt7915_dma_prefetch(dev);
|
||||
@ -1562,9 +1611,10 @@ void mt7915_mac_reset_work(struct work_struct *work)
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
if (phy2)
|
||||
if (phy2) {
|
||||
set_bit(MT76_RESET, &phy2->mt76->state);
|
||||
cancel_delayed_work_sync(&phy2->mt76->mac_work);
|
||||
|
||||
}
|
||||
/* lock/unlock all queues to ensure that no tx is pending */
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
if (ext_phy)
|
||||
@ -1584,7 +1634,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
|
||||
idr_init(&dev->token);
|
||||
|
||||
if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
|
||||
mt7915_dma_reset(&dev->phy);
|
||||
mt7915_dma_reset(dev);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
|
||||
mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
|
||||
@ -1592,6 +1642,8 @@ void mt7915_mac_reset_work(struct work_struct *work)
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
if (phy2)
|
||||
clear_bit(MT76_RESET, &phy2->mt76->state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
@ -1633,39 +1685,30 @@ mt7915_mac_update_mib_stats(struct mt7915_phy *phy)
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
int i, aggr0, aggr1;
|
||||
|
||||
memset(mib, 0, sizeof(*mib));
|
||||
|
||||
mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
|
||||
mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
|
||||
MT_MIB_SDR3_FCS_ERR_MASK);
|
||||
|
||||
aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
|
||||
for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {
|
||||
u32 val, val2;
|
||||
u32 val;
|
||||
|
||||
val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i));
|
||||
|
||||
val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
|
||||
if (val2 > mib->ack_fail_cnt)
|
||||
mib->ack_fail_cnt = val2;
|
||||
|
||||
val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
|
||||
if (val2 > mib->ba_miss_cnt)
|
||||
mib->ba_miss_cnt = val2;
|
||||
mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
|
||||
mib->ack_fail_cnt +=
|
||||
FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
|
||||
|
||||
val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i));
|
||||
val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
|
||||
if (val2 > mib->rts_retries_cnt) {
|
||||
mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
|
||||
mib->rts_retries_cnt = val2;
|
||||
}
|
||||
mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
|
||||
mib->rts_retries_cnt +=
|
||||
FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
|
||||
|
||||
val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));
|
||||
val2 = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i));
|
||||
|
||||
dev->mt76.aggr_stats[aggr0++] += val & 0xffff;
|
||||
dev->mt76.aggr_stats[aggr0++] += val >> 16;
|
||||
dev->mt76.aggr_stats[aggr1++] += val2 & 0xffff;
|
||||
dev->mt76.aggr_stats[aggr1++] += val2 >> 16;
|
||||
|
||||
val = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i));
|
||||
dev->mt76.aggr_stats[aggr1++] += val & 0xffff;
|
||||
dev->mt76.aggr_stats[aggr1++] += val >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,10 @@ enum rx_pkt_type {
|
||||
|
||||
/* RXD DW4 */
|
||||
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
|
||||
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
|
||||
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
|
||||
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
|
||||
|
||||
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
|
||||
#define MT_RXD4_NORMAL_CLS BIT(10)
|
||||
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
|
||||
@ -97,6 +101,17 @@ enum rx_pkt_type {
|
||||
|
||||
#define MT_RXV_HDR_BAND_IDX BIT(24)
|
||||
|
||||
/* RXD GROUP4 */
|
||||
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
|
||||
#define MT_RXD6_TA_LO GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD7_TA_HI GENMASK(31, 0)
|
||||
|
||||
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
|
||||
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
|
||||
|
||||
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
|
||||
|
||||
/* P-RXV */
|
||||
#define MT_PRXV_TX_RATE GENMASK(6, 0)
|
||||
#define MT_PRXV_TX_DCM BIT(4)
|
||||
|
@ -25,6 +25,7 @@ static int mt7915_start(struct ieee80211_hw *hw)
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
bool running;
|
||||
int ret;
|
||||
|
||||
flush_work(&dev->init_work);
|
||||
|
||||
@ -33,21 +34,48 @@ static int mt7915_start(struct ieee80211_hw *hw)
|
||||
running = mt7915_dev_running(dev);
|
||||
|
||||
if (!running) {
|
||||
mt7915_mcu_set_pm(dev, 0, 0);
|
||||
mt7915_mcu_set_mac(dev, 0, true, false);
|
||||
mt7915_mcu_set_scs(dev, 0, true);
|
||||
ret = mt7915_mcu_set_pm(dev, 0, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_mac(dev, 0, true, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_scs(dev, 0, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7915_mac_enable_nf(dev, 0);
|
||||
}
|
||||
|
||||
if (phy != &dev->phy) {
|
||||
mt7915_mcu_set_pm(dev, 1, 0);
|
||||
mt7915_mcu_set_mac(dev, 1, true, false);
|
||||
mt7915_mcu_set_scs(dev, 1, true);
|
||||
ret = mt7915_mcu_set_pm(dev, 1, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_mac(dev, 1, true, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_scs(dev, 1, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7915_mac_enable_nf(dev, 1);
|
||||
}
|
||||
|
||||
mt7915_mcu_set_sku_en(phy, true);
|
||||
mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
|
||||
ret = mt7915_mcu_set_rts_thresh(phy, 0x92b);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_sku_en(phy, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
|
||||
@ -58,9 +86,10 @@ static int mt7915_start(struct ieee80211_hw *hw)
|
||||
if (!running)
|
||||
mt7915_mac_reset_counters(phy);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7915_stop(struct ieee80211_hw *hw)
|
||||
@ -227,7 +256,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
int idx = msta->wcid.idx;
|
||||
|
||||
/* TODO: disable beacon for the bss */
|
||||
mt7915_mcu_add_bss_info(phy, vif, false);
|
||||
mt7915_mcu_add_sta(dev, vif, NULL, false);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt76_testmode_reset(phy->mt76, true);
|
||||
@ -317,7 +347,9 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv :
|
||||
&mvif->sta;
|
||||
struct mt76_wcid *wcid = &msta->wcid;
|
||||
u8 *wcid_keyidx = &wcid->hw_key_idx;
|
||||
int idx = key->keyidx;
|
||||
int err = 0;
|
||||
|
||||
/* The hardware does not support per-STA RX GTK, fallback
|
||||
* to software mode for these.
|
||||
@ -332,6 +364,7 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
/* fall back to sw encryption for unsupported ciphers */
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
wcid_keyidx = &wcid->hw_key_idx2;
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
@ -347,16 +380,24 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
key->hw_key_idx = wcid->idx;
|
||||
wcid->hw_key_idx = idx;
|
||||
} else if (idx == wcid->hw_key_idx) {
|
||||
wcid->hw_key_idx = -1;
|
||||
}
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
if (cmd == SET_KEY)
|
||||
*wcid_keyidx = idx;
|
||||
else if (idx == *wcid_keyidx)
|
||||
*wcid_keyidx = -1;
|
||||
else
|
||||
goto out;
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
||||
cmd == SET_KEY ? key : NULL);
|
||||
|
||||
return mt7915_mcu_add_key(dev, vif, msta, key, cmd);
|
||||
err = mt7915_mcu_add_key(dev, vif, msta, key, cmd);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
|
||||
@ -515,9 +556,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
mt7915_mcu_add_bss_info(phy, vif, info->enable_beacon);
|
||||
mt7915_mcu_add_sta(dev, vif, NULL, info->enable_beacon);
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
mt7915_mcu_add_bss_info(phy, vif, true);
|
||||
mt7915_mcu_add_sta(dev, vif, NULL, true);
|
||||
}
|
||||
|
||||
/* ensure that enable txcmd_mode after bss_info */
|
||||
@ -631,12 +672,13 @@ static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
{
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt7915_mcu_set_rts_thresh(phy, val);
|
||||
ret = mt7915_mcu_set_rts_thresh(phy, val);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -663,22 +705,22 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
|
||||
params->buf_size);
|
||||
mt7915_mcu_add_rx_ba(dev, params, true);
|
||||
ret = mt7915_mcu_add_rx_ba(dev, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
|
||||
mt7915_mcu_add_rx_ba(dev, params, false);
|
||||
ret = mt7915_mcu_add_rx_ba(dev, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
mt7915_mcu_add_tx_ba(dev, params, true);
|
||||
ret = mt7915_mcu_add_tx_ba(dev, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->ampdu_state);
|
||||
mt7915_mcu_add_tx_ba(dev, params, false);
|
||||
ret = mt7915_mcu_add_tx_ba(dev, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
set_bit(tid, &msta->ampdu_state);
|
||||
@ -687,7 +729,7 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->ampdu_state);
|
||||
mt7915_mcu_add_tx_ba(dev, params, false);
|
||||
ret = mt7915_mcu_add_tx_ba(dev, params, false);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
@ -717,13 +759,19 @@ mt7915_get_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_low_level_stats *stats)
|
||||
{
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mib_stats *mib = &phy->mib;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
stats->dot11RTSSuccessCount = mib->rts_cnt;
|
||||
stats->dot11RTSFailureCount = mib->rts_retries_cnt;
|
||||
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
|
||||
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
|
||||
|
||||
memset(mib, 0, sizeof(*mib));
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -833,9 +881,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
|
||||
struct mt7915_sta_stats *stats = &msta->stats;
|
||||
struct rate_info rxrate = {};
|
||||
|
||||
if (mt7915_mcu_get_rx_rate(phy, vif, sta, &sinfo->rxrate) == 0)
|
||||
if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {
|
||||
sinfo->rxrate = rxrate;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
|
||||
}
|
||||
|
||||
if (!stats->tx_rate.legacy && !stats->tx_rate.flags)
|
||||
return;
|
||||
@ -888,6 +939,22 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
|
||||
mt7915_mcu_sta_update_hdr_trans(dev, vif, sta);
|
||||
}
|
||||
|
||||
static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
bool enabled)
|
||||
{
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
|
||||
|
||||
if (enabled)
|
||||
set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
|
||||
else
|
||||
clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
|
||||
|
||||
mt7915_mcu_sta_update_hdr_trans(dev, vif, sta);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7915_ops = {
|
||||
.tx = mt7915_tx,
|
||||
.start = mt7915_start,
|
||||
@ -920,6 +987,7 @@ const struct ieee80211_ops mt7915_ops = {
|
||||
.set_coverage_class = mt7915_set_coverage_class,
|
||||
.sta_statistics = mt7915_sta_statistics,
|
||||
.sta_set_4addr = mt7915_sta_set_4addr,
|
||||
.sta_set_decap_offload = mt7915_sta_set_decap_offload,
|
||||
CFG80211_TESTMODE_CMD(mt76_testmode_cmd)
|
||||
CFG80211_TESTMODE_DUMP(mt76_testmode_dump)
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
|
@ -147,9 +147,10 @@ mt7915_get_he_phy_cap(struct mt7915_phy *phy, struct ieee80211_vif *vif)
|
||||
}
|
||||
|
||||
static u8
|
||||
mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
enum nl80211_band band, struct ieee80211_sta *sta)
|
||||
mt7915_get_phy_mode(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
enum nl80211_band band = mphy->chandef.chan->band;
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
@ -161,12 +162,8 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
he_cap = &sta->he_cap;
|
||||
} else {
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt7915_phy *phy;
|
||||
struct mt7915_vif *mvif;
|
||||
|
||||
mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
phy = mvif->band_idx ? mt7915_ext_phy(dev) : &dev->phy;
|
||||
sband = phy->mt76->hw->wiphy->bands[band];
|
||||
sband = mphy->hw->wiphy->bands[band];
|
||||
|
||||
ht_cap = &sband->ht_cap;
|
||||
vht_cap = &sband->vht_cap;
|
||||
@ -336,6 +333,22 @@ mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt7915_mcu_csa_notify *c;
|
||||
|
||||
c = (struct mt7915_mcu_csa_notify *)skb->data;
|
||||
|
||||
if (c->band_idx && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7915_mcu_csa_finish, mphy->hw);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
@ -344,61 +357,69 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
|
||||
r = (struct mt7915_mcu_rdd_report *)skb->data;
|
||||
|
||||
if (r->idx && dev->mt76.phy2)
|
||||
if (r->band_idx && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
ieee80211_radar_detected(mphy->hw);
|
||||
dev->hw_pattern++;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra,
|
||||
struct rate_info *rate, u16 r)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
u16 ru_idx = le16_to_cpu(ra->ru_idx);
|
||||
u16 flags = 0;
|
||||
bool cck = false;
|
||||
|
||||
rate->mcs = FIELD_GET(MT_RA_RATE_MCS, r);
|
||||
rate->nss = FIELD_GET(MT_RA_RATE_NSS, r) + 1;
|
||||
|
||||
switch (FIELD_GET(MT_RA_RATE_TX_MODE, r)) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
rate->mcs = mt76_get_rate(mphy->dev, sband, rate->mcs, cck);
|
||||
rate->legacy = sband->bitrates[rate->mcs].bitrate;
|
||||
break;
|
||||
case MT_PHY_TYPE_HT:
|
||||
case MT_PHY_TYPE_HT_GF:
|
||||
rate->mcs += (rate->nss - 1) * 8;
|
||||
flags |= RATE_INFO_FLAGS_MCS;
|
||||
if (rate->mcs > 31)
|
||||
return -EINVAL;
|
||||
|
||||
rate->flags = RATE_INFO_FLAGS_MCS;
|
||||
if (ra->gi)
|
||||
flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (rate->mcs > 9)
|
||||
return -EINVAL;
|
||||
|
||||
rate->flags = RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (ra->gi)
|
||||
flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
if (ra->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11)
|
||||
return -EINVAL;
|
||||
|
||||
rate->he_gi = ra->gi;
|
||||
rate->he_dcm = FIELD_GET(MT_RA_RATE_DCM_EN, r);
|
||||
|
||||
flags |= RATE_INFO_FLAGS_HE_MCS;
|
||||
rate->flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
rate->flags = flags;
|
||||
|
||||
if (ru_idx) {
|
||||
switch (ru_idx) {
|
||||
@ -435,6 +456,8 @@ mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -465,11 +488,11 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
/* current rate */
|
||||
mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr);
|
||||
if (!mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr))
|
||||
stats->tx_rate = rate;
|
||||
|
||||
/* probing rate */
|
||||
mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe);
|
||||
if (!mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe))
|
||||
stats->prob_rate = prob_rate;
|
||||
|
||||
if (attempts) {
|
||||
@ -498,7 +521,8 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
|
||||
wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data);
|
||||
wiphy_info(mt76_hw(dev)->wiphy, "%s: %*s", type,
|
||||
(int)(skb->len - sizeof(*rxd)), data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -511,9 +535,7 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
mt7915_mcu_rx_radar_detected(dev, skb);
|
||||
break;
|
||||
case MCU_EXT_EVENT_CSA_NOTIFY:
|
||||
ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7915_mcu_csa_finish, dev);
|
||||
mt7915_mcu_rx_csa_notify(dev, skb);
|
||||
break;
|
||||
case MCU_EXT_EVENT_RATE_REPORT:
|
||||
mt7915_mcu_tx_rate_report(dev, skb);
|
||||
@ -592,7 +614,7 @@ mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta,
|
||||
|
||||
if (!nskb) {
|
||||
nskb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
|
||||
MT7915_WTBL_UPDATE_BA_SIZE);
|
||||
MT7915_WTBL_UPDATE_MAX_SIZE);
|
||||
if (!nskb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -662,8 +684,6 @@ mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
struct mt7915_phy *phy, bool enable)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct bss_info_basic *bss;
|
||||
u16 wlan_idx = mvif->sta.wcid.idx;
|
||||
u32 type = NETWORK_INFRA;
|
||||
@ -713,7 +733,7 @@ mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
|
||||
bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
|
||||
bss->dtim_period = vif->bss_conf.dtim_period;
|
||||
bss->phy_mode = mt7915_get_phy_mode(phy->dev, vif, band, NULL);
|
||||
bss->phy_mode = mt7915_get_phy_mode(phy->mt76, vif, NULL);
|
||||
} else {
|
||||
memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN);
|
||||
}
|
||||
@ -989,8 +1009,10 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (mvif->omac_idx >= REPEATER_BSSID_START)
|
||||
if (mvif->omac_idx >= REPEATER_BSSID_START) {
|
||||
mt7915_mcu_muar_config(phy, vif, false, enable);
|
||||
mt7915_mcu_muar_config(phy, vif, true, enable);
|
||||
}
|
||||
|
||||
skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL,
|
||||
MT7915_BSS_UPDATE_MAX_SIZE);
|
||||
@ -1188,6 +1210,9 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev,
|
||||
|
||||
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl,
|
||||
&skb);
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr);
|
||||
|
||||
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
@ -1685,6 +1710,7 @@ mt7915_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
return;
|
||||
|
||||
msta = (struct mt7915_sta *)sta->drv_priv;
|
||||
htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
|
||||
if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) {
|
||||
htr->to_ds = true;
|
||||
htr->from_ds = true;
|
||||
@ -1704,6 +1730,9 @@ int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev,
|
||||
return -ENOMEM;
|
||||
|
||||
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb);
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(WTBL_UPDATE),
|
||||
@ -1728,6 +1757,9 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
|
||||
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl,
|
||||
&skb);
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
@ -2045,25 +2077,30 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
|
||||
static void
|
||||
mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
|
||||
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
|
||||
struct mt76_phy *mphy = &dev->mphy;
|
||||
enum nl80211_band band;
|
||||
struct sta_rec_ra *ra;
|
||||
struct tlv *tlv;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
u32 supp_rate = sta->supp_rates[band];
|
||||
int n_rates = hweight32(supp_rate);
|
||||
u32 cap = sta->wme ? STA_CAP_WMM : 0;
|
||||
u32 supp_rate, n_rates, cap = sta->wme ? STA_CAP_WMM : 0;
|
||||
u8 i, nss = sta->rx_nss, mcs = 0;
|
||||
|
||||
tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
|
||||
|
||||
ra = (struct sta_rec_ra *)tlv;
|
||||
|
||||
if (msta->wcid.ext_phy && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
band = mphy->chandef.chan->band;
|
||||
supp_rate = sta->supp_rates[band];
|
||||
n_rates = hweight32(supp_rate);
|
||||
|
||||
ra->valid = true;
|
||||
ra->auto_rate = true;
|
||||
ra->phy_mode = mt7915_get_phy_mode(dev, vif, band, sta);
|
||||
ra->channel = chandef->chan->hw_value;
|
||||
ra->phy_mode = mt7915_get_phy_mode(mphy, vif, sta);
|
||||
ra->channel = mphy->chandef.chan->hw_value;
|
||||
ra->bw = sta->bandwidth;
|
||||
ra->rate_len = n_rates;
|
||||
ra->phy.bw = sta->bandwidth;
|
||||
@ -2253,6 +2290,9 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
|
||||
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET,
|
||||
sta_wtbl, &skb);
|
||||
if (IS_ERR(wtbl_hdr))
|
||||
return PTR_ERR(wtbl_hdr);
|
||||
|
||||
if (enable) {
|
||||
mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr);
|
||||
mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr);
|
||||
@ -2411,6 +2451,17 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
struct bss_info_bcn *bcn;
|
||||
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
|
||||
|
||||
rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len);
|
||||
if (IS_ERR(rskb))
|
||||
return PTR_ERR(rskb);
|
||||
|
||||
tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
|
||||
bcn = (struct bss_info_bcn *)tlv;
|
||||
bcn->enable = en;
|
||||
|
||||
if (!en)
|
||||
goto out;
|
||||
|
||||
skb = ieee80211_beacon_get_template(hw, vif, &offs);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
@ -2421,16 +2472,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len);
|
||||
if (IS_ERR(rskb)) {
|
||||
dev_kfree_skb(skb);
|
||||
return PTR_ERR(rskb);
|
||||
}
|
||||
|
||||
tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
|
||||
bcn = (struct bss_info_bcn *)tlv;
|
||||
bcn->enable = en;
|
||||
|
||||
if (mvif->band_idx) {
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
@ -2441,6 +2482,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
mt7915_mcu_beacon_cont(dev, rskb, skb, bcn, &offs);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
out:
|
||||
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
|
||||
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
@ -2500,11 +2542,9 @@ static int mt7915_mcu_start_patch(struct mt7915_dev *dev)
|
||||
|
||||
static int mt7915_driver_own(struct mt7915_dev *dev)
|
||||
{
|
||||
u32 reg = mt7915_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0);
|
||||
|
||||
mt76_wr(dev, reg, MT_TOP_LPCR_HOST_DRV_OWN);
|
||||
if (!mt76_poll_msec(dev, reg, MT_TOP_LPCR_HOST_FW_OWN,
|
||||
0, 500)) {
|
||||
mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_DRV_OWN);
|
||||
if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND0,
|
||||
MT_TOP_LPCR_HOST_FW_OWN, 0, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for driver own\n");
|
||||
return -EIO;
|
||||
}
|
||||
@ -2743,20 +2783,6 @@ out:
|
||||
static int mt7915_load_firmware(struct mt7915_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
u32 val, reg = mt7915_reg_map_l1(dev, MT_TOP_MISC);
|
||||
|
||||
val = FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD);
|
||||
|
||||
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, val, 1000)) {
|
||||
/* restart firmware once */
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE,
|
||||
val, 1000)) {
|
||||
dev_err(dev->mt76.dev,
|
||||
"Firmware is not ready for download\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt7915_load_patch(dev);
|
||||
if (ret)
|
||||
@ -2766,7 +2792,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE,
|
||||
if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
|
||||
FIELD_PREP(MT_TOP_MISC_FW_STATE,
|
||||
FW_STATE_WACPU_RDY), 1000)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
|
||||
@ -2854,21 +2880,39 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
|
||||
|
||||
void mt7915_mcu_exit(struct mt7915_dev *dev)
|
||||
{
|
||||
u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC);
|
||||
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE,
|
||||
if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
|
||||
FIELD_PREP(MT_TOP_MISC_FW_STATE,
|
||||
FW_STATE_FW_DOWNLOAD), 1000)) {
|
||||
dev_err(dev->mt76.dev, "Failed to exit mcu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reg = mt7915_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0);
|
||||
mt76_wr(dev, reg, MT_TOP_LPCR_HOST_FW_OWN);
|
||||
mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_FW_OWN);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_mcu_set_rx_hdr_trans_blacklist(struct mt7915_dev *dev, int band)
|
||||
{
|
||||
struct {
|
||||
u8 operation;
|
||||
u8 count;
|
||||
u8 _rsv[2];
|
||||
u8 index;
|
||||
u8 enable;
|
||||
__le16 etype;
|
||||
} req = {
|
||||
.operation = 1,
|
||||
.count = 1,
|
||||
.enable = 1,
|
||||
.etype = cpu_to_le16(ETH_P_PAE),
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),
|
||||
&req, sizeof(req), false);
|
||||
}
|
||||
|
||||
int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,
|
||||
bool enable, bool hdr_trans)
|
||||
{
|
||||
@ -2899,6 +2943,9 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hdr_trans)
|
||||
mt7915_mcu_set_rx_hdr_trans_blacklist(dev, band);
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MAC_INIT_CTRL),
|
||||
&req_mac, sizeof(req_mac), true);
|
||||
}
|
||||
@ -3182,7 +3229,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
|
||||
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
|
||||
@ -3501,9 +3548,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt7915_mcu_phy_rx_info *res;
|
||||
struct sk_buff *skb;
|
||||
u16 flags = 0;
|
||||
int ret;
|
||||
int i;
|
||||
bool cck = false;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(PHY_STAT_INFO),
|
||||
&req, sizeof(req), true, &skb);
|
||||
@ -3517,48 +3563,53 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
|
||||
switch (res->mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (rate->mcs != (sband->bitrates[i].hw_value & 0xf))
|
||||
continue;
|
||||
|
||||
rate->legacy = sband->bitrates[i].bitrate;
|
||||
break;
|
||||
}
|
||||
rate->mcs = mt76_get_rate(&dev->mt76, sband, rate->mcs, cck);
|
||||
rate->legacy = sband->bitrates[rate->mcs].bitrate;
|
||||
break;
|
||||
case MT_PHY_TYPE_HT:
|
||||
case MT_PHY_TYPE_HT_GF:
|
||||
if (rate->mcs > 31)
|
||||
return -EINVAL;
|
||||
|
||||
flags |= RATE_INFO_FLAGS_MCS;
|
||||
if (rate->mcs > 31) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rate->flags = RATE_INFO_FLAGS_MCS;
|
||||
if (res->gi)
|
||||
flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (rate->mcs > 9) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rate->flags = RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (res->gi)
|
||||
flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
case MT_PHY_TYPE_HE_TB:
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
if (res->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rate->he_gi = res->gi;
|
||||
|
||||
flags |= RATE_INFO_FLAGS_HE_MCS;
|
||||
rate->flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rate->flags = flags;
|
||||
|
||||
switch (res->bw) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
@ -3575,7 +3626,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
@ -68,10 +68,19 @@ struct mt7915_mcu_rxd {
|
||||
u8 s2d_index;
|
||||
};
|
||||
|
||||
struct mt7915_mcu_csa_notify {
|
||||
struct mt7915_mcu_rxd rxd;
|
||||
|
||||
u8 omac_idx;
|
||||
u8 csa_count;
|
||||
u8 band_idx;
|
||||
u8 rsv;
|
||||
} __packed;
|
||||
|
||||
struct mt7915_mcu_rdd_report {
|
||||
struct mt7915_mcu_rxd rxd;
|
||||
|
||||
u8 idx;
|
||||
u8 band_idx;
|
||||
u8 long_detected;
|
||||
u8 constant_prf_detected;
|
||||
u8 staggered_prf_detected;
|
||||
@ -1080,9 +1089,6 @@ enum {
|
||||
sizeof(struct tlv) + \
|
||||
MT7915_WTBL_UPDATE_MAX_SIZE)
|
||||
|
||||
#define MT7915_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
|
||||
sizeof(struct wtbl_ba))
|
||||
|
||||
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct bss_info_omac) + \
|
||||
sizeof(struct bss_info_basic) +\
|
||||
|
152
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
Normal file
152
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
Normal file
@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include "mt7915.h"
|
||||
|
||||
static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
|
||||
|
||||
mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base);
|
||||
/* use read to push write */
|
||||
mt76_rr(dev, MT_HIF_REMAP_L1);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L1 + offset;
|
||||
}
|
||||
|
||||
static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
|
||||
|
||||
mt76_rmw_field(dev, MT_HIF_REMAP_L2, MT_HIF_REMAP_L2_MASK, base);
|
||||
/* use read to push write */
|
||||
mt76_rr(dev, MT_HIF_REMAP_L2);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L2 + offset;
|
||||
}
|
||||
|
||||
static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
static const struct {
|
||||
u32 phys;
|
||||
u32 mapped;
|
||||
u32 size;
|
||||
} fixed_map[] = {
|
||||
{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
|
||||
{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
|
||||
{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
|
||||
{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
|
||||
{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
|
||||
{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
|
||||
{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
|
||||
{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
|
||||
{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
|
||||
{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
|
||||
{ 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
|
||||
{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
|
||||
{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
|
||||
{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
|
||||
{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
|
||||
{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
|
||||
{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
|
||||
{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
|
||||
{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
|
||||
{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
|
||||
{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
|
||||
{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
|
||||
{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
|
||||
{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
|
||||
{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
|
||||
{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
|
||||
{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
|
||||
{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
|
||||
{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
|
||||
{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
|
||||
{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
|
||||
{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
|
||||
{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
|
||||
{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
|
||||
{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
|
||||
{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
|
||||
{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
|
||||
{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
|
||||
};
|
||||
int i;
|
||||
|
||||
if (addr < 0x100000)
|
||||
return addr;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
|
||||
u32 ofs;
|
||||
|
||||
if (addr < fixed_map[i].phys)
|
||||
continue;
|
||||
|
||||
ofs = addr - fixed_map[i].phys;
|
||||
if (ofs > fixed_map[i].size)
|
||||
continue;
|
||||
|
||||
return fixed_map[i].mapped + ofs;
|
||||
}
|
||||
|
||||
if ((addr >= 0x18000000 && addr < 0x18c00000) ||
|
||||
(addr >= 0x70000000 && addr < 0x78000000) ||
|
||||
(addr >= 0x7c000000 && addr < 0x7c400000))
|
||||
return mt7915_reg_map_l1(dev, addr);
|
||||
|
||||
return mt7915_reg_map_l2(dev, addr);
|
||||
}
|
||||
|
||||
static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
u32 addr = __mt7915_reg_addr(dev, offset);
|
||||
|
||||
return dev->bus_ops->rr(mdev, addr);
|
||||
}
|
||||
|
||||
static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
u32 addr = __mt7915_reg_addr(dev, offset);
|
||||
|
||||
dev->bus_ops->wr(mdev, addr, val);
|
||||
}
|
||||
|
||||
static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
u32 addr = __mt7915_reg_addr(dev, offset);
|
||||
|
||||
return dev->bus_ops->rmw(mdev, addr, mask, val);
|
||||
}
|
||||
|
||||
int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq)
|
||||
{
|
||||
struct mt76_bus_ops *bus_ops;
|
||||
struct mt7915_dev *dev;
|
||||
|
||||
dev = container_of(mdev, struct mt7915_dev, mt76);
|
||||
mt76_mmio_init(&dev->mt76, mem_base);
|
||||
|
||||
dev->bus_ops = dev->mt76.bus;
|
||||
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
|
||||
GFP_KERNEL);
|
||||
if (!bus_ops)
|
||||
return -ENOMEM;
|
||||
|
||||
bus_ops->rr = mt7915_rr;
|
||||
bus_ops->wr = mt7915_wr;
|
||||
bus_ops->rmw = mt7915_rmw;
|
||||
dev->mt76.bus = bus_ops;
|
||||
|
||||
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
|
||||
return 0;
|
||||
}
|
@ -108,11 +108,11 @@ struct mt7915_vif {
|
||||
};
|
||||
|
||||
struct mib_stats {
|
||||
u16 ack_fail_cnt;
|
||||
u16 fcs_err_cnt;
|
||||
u16 rts_cnt;
|
||||
u16 rts_retries_cnt;
|
||||
u16 ba_miss_cnt;
|
||||
u32 ack_fail_cnt;
|
||||
u32 fcs_err_cnt;
|
||||
u32 rts_cnt;
|
||||
u32 rts_retries_cnt;
|
||||
u32 ba_miss_cnt;
|
||||
};
|
||||
|
||||
struct mt7915_hif {
|
||||
@ -142,7 +142,7 @@ struct mt7915_phy {
|
||||
u8 rdd_state;
|
||||
int dfs_state;
|
||||
|
||||
__le32 rx_ampdu_ts;
|
||||
u32 rx_ampdu_ts;
|
||||
u32 ampdu_ref;
|
||||
|
||||
struct mib_stats mib;
|
||||
@ -394,80 +394,6 @@ static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
|
||||
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
|
||||
|
||||
mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base);
|
||||
/* use read to push write */
|
||||
mt76_rr(dev, MT_HIF_REMAP_L1);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L1 + offset;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
mt7915_l1_rr(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
return mt76_rr(dev, mt7915_reg_map_l1(dev, addr));
|
||||
}
|
||||
|
||||
static inline void
|
||||
mt7915_l1_wr(struct mt7915_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mt76_wr(dev, mt7915_reg_map_l1(dev, addr), val);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
mt7915_l1_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val)
|
||||
{
|
||||
val |= mt7915_l1_rr(dev, addr) & ~mask;
|
||||
mt7915_l1_wr(dev, addr, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#define mt7915_l1_set(dev, addr, val) mt7915_l1_rmw(dev, addr, 0, val)
|
||||
#define mt7915_l1_clear(dev, addr, val) mt7915_l1_rmw(dev, addr, val, 0)
|
||||
|
||||
static inline u32
|
||||
mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
|
||||
|
||||
mt76_rmw_field(dev, MT_HIF_REMAP_L2, MT_HIF_REMAP_L2_MASK, base);
|
||||
/* use read to push write */
|
||||
mt76_rr(dev, MT_HIF_REMAP_L2);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L2 + offset;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
mt7915_l2_rr(struct mt7915_dev *dev, u32 addr)
|
||||
{
|
||||
return mt76_rr(dev, mt7915_reg_map_l2(dev, addr));
|
||||
}
|
||||
|
||||
static inline void
|
||||
mt7915_l2_wr(struct mt7915_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mt76_wr(dev, mt7915_reg_map_l2(dev, addr), val);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
mt7915_l2_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val)
|
||||
{
|
||||
val |= mt7915_l2_rr(dev, addr) & ~mask;
|
||||
mt7915_l2_wr(dev, addr, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#define mt7915_l2_set(dev, addr, val) mt7915_l2_rmw(dev, addr, 0, val)
|
||||
#define mt7915_l2_clear(dev, addr, val) mt7915_l2_rmw(dev, addr, val, 0)
|
||||
|
||||
bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask);
|
||||
void mt7915_mac_reset_counters(struct mt7915_phy *phy);
|
||||
void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
|
||||
@ -486,6 +412,7 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
void mt7915_mac_work(struct work_struct *work);
|
||||
void mt7915_mac_reset_work(struct work_struct *work);
|
||||
void mt7915_mac_sta_rc_work(struct work_struct *work);
|
||||
int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq);
|
||||
int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -201,7 +201,7 @@ static void mt7915_pci_init_hif2(struct mt7915_dev *dev)
|
||||
}
|
||||
|
||||
/* master switch of PCIe tnterrupt enable */
|
||||
mt7915_l1_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
|
||||
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
|
||||
}
|
||||
|
||||
static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
|
||||
@ -274,15 +274,12 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
|
||||
mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt7915_l1_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
ret = mt7915_mmio_init(mdev, pcim_iomap_table(pdev)[0], pdev->irq);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* master switch of PCIe tnterrupt enable */
|
||||
mt7915_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
|
||||
ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||
|
@ -4,6 +4,11 @@
|
||||
#ifndef __MT7915_REGS_H
|
||||
#define __MT7915_REGS_H
|
||||
|
||||
/* MCU WFDMA0 */
|
||||
#define MT_MCU_WFDMA0_BASE 0x2000
|
||||
#define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
|
||||
#define MT_MCU_WFDMA0_DUMMY_CR MT_MCU_WFDMA0(0x120)
|
||||
|
||||
/* MCU WFDMA1 */
|
||||
#define MT_MCU_WFDMA1_BASE 0x3000
|
||||
#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs))
|
||||
@ -396,6 +401,14 @@
|
||||
#define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
|
||||
#define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2)
|
||||
|
||||
#define MT_TOP_RGU_BASE 0xf0000
|
||||
#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
|
||||
#define MT_TOP_PWR_KEY (0x5746 << 16)
|
||||
#define MT_TOP_PWR_SW_RST BIT(0)
|
||||
#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2)
|
||||
#define MT_TOP_PWR_HW_CTRL BIT(4)
|
||||
#define MT_TOP_PWR_PWR_ON BIT(7)
|
||||
|
||||
#define MT_INFRA_CFG_BASE 0xf1000
|
||||
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
|
||||
|
||||
|
@ -2,4 +2,6 @@
|
||||
|
||||
obj-$(CONFIG_MT7921E) += mt7921e.o
|
||||
|
||||
mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o trace.o
|
||||
|
@ -44,14 +44,13 @@ mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
|
||||
range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bound); i++)
|
||||
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1;
|
||||
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
|
||||
|
||||
seq_printf(file, "\nPhy0\n");
|
||||
|
||||
seq_printf(file, "Length: %8d | ", bound[0]);
|
||||
for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
|
||||
seq_printf(file, "%3d -%3d | ",
|
||||
bound[i] + 1, bound[i + 1]);
|
||||
seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]);
|
||||
|
||||
seq_puts(file, "\nCount: ");
|
||||
for (i = 0; i < ARRAY_SIZE(bound); i++)
|
||||
@ -152,7 +151,6 @@ mt7921_pm_set(void *data, u64 val)
|
||||
{
|
||||
struct mt7921_dev *dev = data;
|
||||
struct mt76_phy *mphy = dev->phy.mt76;
|
||||
int ret = 0;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
@ -163,7 +161,7 @@ mt7921_pm_set(void *data, u64 val)
|
||||
mt7921_pm_interface_iter, mphy->priv);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -299,7 +299,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7921_poll_tx, NAPI_POLL_WEIGHT);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
@ -323,7 +323,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)
|
||||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
mt76_set(dev, 0x54000120, BIT(1));
|
||||
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
|
||||
/* enable interrupts for TX/RX rings */
|
||||
mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
|
@ -77,6 +77,9 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
||||
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
|
||||
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||
|
||||
phy->slottime = 9;
|
||||
|
||||
hw->sta_data_size = sizeof(struct mt7921_sta);
|
||||
@ -95,6 +98,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
wiphy->reg_notifier = mt7921_regd_notifier;
|
||||
|
||||
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
@ -142,7 +146,7 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
|
||||
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
|
||||
}
|
||||
|
||||
static void mt7921_mac_init(struct mt7921_dev *dev)
|
||||
void mt7921_mac_init(struct mt7921_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -232,7 +236,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
spin_lock_init(&dev->sta_poll_lock);
|
||||
|
||||
init_waitqueue_head(&dev->reset_wait);
|
||||
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
|
||||
|
||||
ret = mt7921_init_hardware(dev);
|
||||
@ -250,9 +253,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
|
||||
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
|
||||
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
|
||||
|
||||
@ -273,8 +273,6 @@ void mt7921_unregister_device(struct mt7921_dev *dev)
|
||||
{
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt7921_mcu_exit(dev);
|
||||
mt7921_dma_cleanup(dev);
|
||||
|
||||
mt7921_tx_token_put(dev);
|
||||
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
|
@ -9,8 +9,6 @@
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
|
||||
|
||||
#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
|
||||
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
|
||||
IEEE80211_RADIOTAP_HE_##f)
|
||||
@ -51,14 +49,6 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask)
|
||||
0, 5000);
|
||||
}
|
||||
|
||||
static u32 mt7921_mac_wtbl_lmac_addr(struct mt7921_dev *dev, u16 wcid)
|
||||
{
|
||||
mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
|
||||
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
|
||||
|
||||
return MT_WTBL_LMAC_OFFS(wcid, 0);
|
||||
}
|
||||
|
||||
static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
|
||||
{
|
||||
static const u8 ac_to_tid[] = {
|
||||
@ -95,7 +85,7 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
|
||||
spin_unlock_bh(&dev->sta_poll_lock);
|
||||
|
||||
idx = msta->wcid.idx;
|
||||
addr = mt7921_mac_wtbl_lmac_addr(dev, idx) + 20 * 4;
|
||||
addr = MT_WTBL_LMAC_OFFS(idx, 0) + 20 * 4;
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
u32 tx_last = msta->airtime_ac[i];
|
||||
@ -285,6 +275,37 @@ mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy,
|
||||
status->freq = ieee80211_channel_to_frequency(chfreq, status->band);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct sk_buff *skb = priv;
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
|
||||
|
||||
if (status->signal > 0)
|
||||
return;
|
||||
|
||||
if (!ether_addr_equal(vif->addr, hdr->addr1))
|
||||
return;
|
||||
|
||||
ewma_rssi_add(&mvif->rssi, -status->signal);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
|
||||
|
||||
if (!ieee80211_is_assoc_resp(hdr->frame_control) &&
|
||||
!ieee80211_is_auth(hdr->frame_control))
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_mac_rssi_iter, skb);
|
||||
}
|
||||
|
||||
int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
@ -349,19 +370,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
|
||||
}
|
||||
|
||||
if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (phy->rx_ampdu_ts != rxd[14]) {
|
||||
if (!++phy->ampdu_ref)
|
||||
phy->ampdu_ref++;
|
||||
}
|
||||
phy->rx_ampdu_ts = rxd[14];
|
||||
|
||||
status->ampdu_ref = phy->ampdu_ref;
|
||||
}
|
||||
|
||||
remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2);
|
||||
|
||||
if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
|
||||
@ -393,6 +401,22 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_2) {
|
||||
status->timestamp = le32_to_cpu(rxd[0]);
|
||||
status->flag |= RX_FLAG_MACTIME_START;
|
||||
|
||||
if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
|
||||
status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
||||
/* all subframes of an A-MPDU have the same timestamp */
|
||||
if (phy->rx_ampdu_ts != status->timestamp) {
|
||||
if (!++phy->ampdu_ref)
|
||||
phy->ampdu_ref++;
|
||||
}
|
||||
phy->rx_ampdu_ts = status->timestamp;
|
||||
|
||||
status->ampdu_ref = phy->ampdu_ref;
|
||||
}
|
||||
|
||||
rxd += 2;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
@ -400,7 +424,9 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
|
||||
/* RXD Group 3 - P-RXV */
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
|
||||
u32 v0, v1, v2;
|
||||
u8 stbc, gi;
|
||||
u32 v0, v1;
|
||||
bool cck;
|
||||
|
||||
rxv = rxd;
|
||||
rxd += 2;
|
||||
@ -409,7 +435,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
|
||||
v0 = le32_to_cpu(rxv[0]);
|
||||
v1 = le32_to_cpu(rxv[1]);
|
||||
v2 = le32_to_cpu(rxv[2]);
|
||||
|
||||
if (v0 & MT_PRXV_HT_AD_CODE)
|
||||
status->enc_flags |= RX_ENC_FLAG_LDPC;
|
||||
@ -429,18 +454,12 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
status->chain_signal[i]);
|
||||
}
|
||||
|
||||
/* RXD Group 5 - C-RXV */
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
|
||||
u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
|
||||
u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
|
||||
bool cck = false;
|
||||
|
||||
rxd += 18;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
stbc = FIELD_GET(MT_PRXV_STBC, v0);
|
||||
gi = FIELD_GET(MT_PRXV_SGI, v0);
|
||||
cck = false;
|
||||
|
||||
idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
|
||||
mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
|
||||
mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
|
||||
|
||||
switch (mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
@ -482,9 +501,10 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status->rate_idx = i;
|
||||
|
||||
switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) {
|
||||
switch (FIELD_GET(MT_PRXV_FRAME_MODE, v0)) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
@ -510,6 +530,11 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
|
||||
if (mode < MT_PHY_TYPE_HE_SU && gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
|
||||
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
|
||||
rxd += 18;
|
||||
if ((u8 *)rxd - skb->data >= skb->len)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,6 +546,8 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
mt76_insert_ccmp_hdr(skb, key_id);
|
||||
}
|
||||
|
||||
mt7921_mac_assoc_rssi(dev, skb);
|
||||
|
||||
if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
|
||||
mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
|
||||
|
||||
@ -530,7 +557,7 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
|
||||
status->aggr = unicast &&
|
||||
!ieee80211_is_qos_nullfunc(hdr->frame_control);
|
||||
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
|
||||
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
|
||||
|
||||
return 0;
|
||||
@ -1183,43 +1210,76 @@ void mt7921_update_channel(struct mt76_dev *mdev)
|
||||
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7921_wait_reset_state(struct mt7921_dev *dev, u32 state)
|
||||
int mt7921_wfsys_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
bool ret;
|
||||
mt76_set(dev, 0x70002600, BIT(0));
|
||||
msleep(200);
|
||||
mt76_clear(dev, 0x70002600, BIT(0));
|
||||
|
||||
ret = wait_event_timeout(dev->reset_wait,
|
||||
(READ_ONCE(dev->reset_state) & state),
|
||||
MT7921_RESET_TIMEOUT);
|
||||
|
||||
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
|
||||
return ret;
|
||||
return __mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B,
|
||||
WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_dma_reset(struct mt7921_phy *phy)
|
||||
mt7921_dma_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
struct mt7921_dev *dev = phy->dev;
|
||||
int i;
|
||||
|
||||
/* reset */
|
||||
mt76_clear(dev, MT_WFDMA0_RST,
|
||||
MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST);
|
||||
|
||||
mt76_set(dev, MT_WFDMA0_RST,
|
||||
MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST);
|
||||
|
||||
/* disable WFDMA0 */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true);
|
||||
/* reset hw queues */
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true);
|
||||
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
}
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
|
||||
|
||||
/* re-init prefetch settings after reset */
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
|
||||
|
||||
/* configure perfetch settings */
|
||||
mt7921_dma_prefetch(dev);
|
||||
|
||||
/* reset dma idx */
|
||||
mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
|
||||
|
||||
/* configure delay interrupt */
|
||||
mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
|
||||
|
||||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
|
||||
MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
|
||||
MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
|
||||
|
||||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
|
||||
/* enable interrupts for TX/RX rings */
|
||||
mt7921_irq_enable(dev,
|
||||
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
}
|
||||
|
||||
void mt7921_tx_token_put(struct mt7921_dev *dev)
|
||||
@ -1243,71 +1303,125 @@ void mt7921_tx_token_put(struct mt7921_dev *dev)
|
||||
idr_destroy(&dev->token);
|
||||
}
|
||||
|
||||
/* system error recovery */
|
||||
void mt7921_mac_reset_work(struct work_struct *work)
|
||||
static void
|
||||
mt7921_vif_connect_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_dev *dev;
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mvif->phy->dev;
|
||||
|
||||
dev = container_of(work, struct mt7921_dev, reset_work);
|
||||
ieee80211_disconnect(vif, true);
|
||||
|
||||
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
|
||||
return;
|
||||
mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true);
|
||||
mt7921_mcu_set_tx(dev, vif);
|
||||
}
|
||||
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
static int
|
||||
mt7921_mac_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
|
||||
|
||||
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
/* lock/unlock all queues to ensure that no tx is pending */
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
napi_disable(&dev->mt76.napi[0]);
|
||||
napi_disable(&dev->mt76.napi[1]);
|
||||
napi_disable(&dev->mt76.napi[2]);
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
|
||||
|
||||
mt7921_tx_token_put(dev);
|
||||
idr_init(&dev->token);
|
||||
|
||||
if (mt7921_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
|
||||
mt7921_dma_reset(&dev->phy);
|
||||
/* clean up hw queues */
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
|
||||
mt7921_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
|
||||
|
||||
mt7921_wfsys_reset(dev);
|
||||
mt7921_dma_reset(dev);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
napi_enable(&dev->mt76.napi[i]);
|
||||
napi_schedule(&dev->mt76.napi[i]);
|
||||
}
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
|
||||
napi_enable(&dev->mt76.napi[0]);
|
||||
napi_schedule(&dev->mt76.napi[0]);
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
napi_enable(&dev->mt76.napi[1]);
|
||||
napi_schedule(&dev->mt76.napi[1]);
|
||||
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt7921_irq_enable(dev,
|
||||
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
|
||||
napi_enable(&dev->mt76.napi[2]);
|
||||
napi_schedule(&dev->mt76.napi[2]);
|
||||
err = mt7921_run_firmware(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ieee80211_wake_queues(mt76_hw(dev));
|
||||
err = mt7921_mcu_set_eeprom(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
|
||||
mt7921_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
|
||||
mt7921_mac_init(dev);
|
||||
return __mt7921_start(&dev->phy);
|
||||
}
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
/* system error recovery */
|
||||
void mt7921_mac_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct mt7921_dev *dev;
|
||||
int i;
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
|
||||
MT7921_WATCHDOG_TIME);
|
||||
dev = container_of(work, struct mt7921_dev, reset_work);
|
||||
hw = mt76_hw(dev);
|
||||
|
||||
dev_err(dev->mt76.dev, "chip reset\n");
|
||||
ieee80211_stop_queues(hw);
|
||||
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
cancel_delayed_work_sync(&dev->pm.ps_work);
|
||||
cancel_work_sync(&dev->pm.wake_work);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (!mt7921_mac_reset(dev))
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip reset failed\n");
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
ieee80211_iterate_active_interfaces(hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_vif_connect_iter, 0);
|
||||
}
|
||||
|
||||
void mt7921_reset(struct mt76_dev *mdev)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
|
||||
queue_work(dev->mt76.wq, &dev->reset_work);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1317,31 +1431,20 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy)
|
||||
struct mib_stats *mib = &phy->mib;
|
||||
int i, aggr0 = 0, aggr1;
|
||||
|
||||
memset(mib, 0, sizeof(*mib));
|
||||
|
||||
mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(0),
|
||||
mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0),
|
||||
MT_MIB_SDR3_FCS_ERR_MASK);
|
||||
mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0),
|
||||
MT_MIB_ACK_FAIL_COUNT_MASK);
|
||||
mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0),
|
||||
MT_MIB_BA_FAIL_COUNT_MASK);
|
||||
mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0),
|
||||
MT_MIB_RTS_COUNT_MASK);
|
||||
mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0),
|
||||
MT_MIB_RTS_FAIL_COUNT_MASK);
|
||||
|
||||
for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {
|
||||
u32 val, val2;
|
||||
|
||||
val = mt76_rr(dev, MT_MIB_MB_SDR1(0, i));
|
||||
|
||||
val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
|
||||
if (val2 > mib->ack_fail_cnt)
|
||||
mib->ack_fail_cnt = val2;
|
||||
|
||||
val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
|
||||
if (val2 > mib->ba_miss_cnt)
|
||||
mib->ba_miss_cnt = val2;
|
||||
|
||||
val = mt76_rr(dev, MT_MIB_MB_SDR0(0, i));
|
||||
val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
|
||||
if (val2 > mib->rts_retries_cnt) {
|
||||
mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
|
||||
mib->rts_retries_cnt = val2;
|
||||
}
|
||||
|
||||
val = mt76_rr(dev, MT_TX_AGG_CNT(0, i));
|
||||
val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
|
||||
|
||||
@ -1399,7 +1502,7 @@ void mt7921_mac_work(struct work_struct *work)
|
||||
if (++phy->sta_work_count == 10) {
|
||||
phy->sta_work_count = 0;
|
||||
mt7921_mac_sta_stats_work(phy);
|
||||
};
|
||||
}
|
||||
|
||||
mt7921_mutex_release(phy->dev);
|
||||
|
||||
@ -1503,8 +1606,10 @@ void mt7921_coredump_work(struct work_struct *work)
|
||||
break;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ)
|
||||
break;
|
||||
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(data, skb->data, skb->len);
|
||||
data += skb->len;
|
||||
@ -1513,4 +1618,5 @@ void mt7921_coredump_work(struct work_struct *work)
|
||||
}
|
||||
dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
|
||||
GFP_KERNEL);
|
||||
mt7921_reset(&dev->mt76);
|
||||
}
|
||||
|
@ -97,18 +97,24 @@ enum rx_pkt_type {
|
||||
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
|
||||
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
|
||||
|
||||
/* P-RXV */
|
||||
/* P-RXV DW0 */
|
||||
#define MT_PRXV_TX_RATE GENMASK(6, 0)
|
||||
#define MT_PRXV_TX_DCM BIT(4)
|
||||
#define MT_PRXV_TX_ER_SU_106T BIT(5)
|
||||
#define MT_PRXV_NSTS GENMASK(9, 7)
|
||||
#define MT_PRXV_HT_AD_CODE BIT(11)
|
||||
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
|
||||
#define MT_PRXV_SGI GENMASK(16, 15)
|
||||
#define MT_PRXV_STBC GENMASK(23, 22)
|
||||
#define MT_PRXV_TX_MODE GENMASK(27, 24)
|
||||
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
|
||||
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
|
||||
|
||||
/* P-RXV DW1 */
|
||||
#define MT_PRXV_RCPI3 GENMASK(31, 24)
|
||||
#define MT_PRXV_RCPI2 GENMASK(23, 16)
|
||||
#define MT_PRXV_RCPI1 GENMASK(15, 8)
|
||||
#define MT_PRXV_RCPI0 GENMASK(7, 0)
|
||||
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
|
||||
|
||||
/* C-RXV */
|
||||
#define MT_CRXV_HT_STBC GENMASK(1, 0)
|
||||
|
@ -125,10 +125,6 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
|
||||
|
||||
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
@ -169,28 +165,44 @@ void mt7921_set_stream_he_caps(struct mt7921_phy *phy)
|
||||
}
|
||||
}
|
||||
|
||||
static int mt7921_start(struct ieee80211_hw *hw)
|
||||
int __mt7921_start(struct mt7921_phy *phy)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
int err;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
err = mt76_connac_mcu_set_mac_enable(mphy->dev, 0, true, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
|
||||
mt76_connac_mcu_set_channel_domain(phy->mt76);
|
||||
err = mt76_connac_mcu_set_channel_domain(mphy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
|
||||
mt7921_mac_reset_counters(phy);
|
||||
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
set_bit(MT76_STATE_RUNNING, &mphy->state);
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
|
||||
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
|
||||
MT7921_WATCHDOG_TIME);
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7921_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
int err;
|
||||
|
||||
mt7921_mutex_acquire(phy->dev);
|
||||
err = __mt7921_start(phy);
|
||||
mt7921_mutex_release(phy->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mt7921_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
@ -224,9 +236,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
|
||||
if (i)
|
||||
return i - 1;
|
||||
|
||||
if (type != NL80211_IFTYPE_STATION)
|
||||
break;
|
||||
|
||||
/* next, try to find a free repeater entry for the sta */
|
||||
i = get_free_idx(mask >> REPEATER_BSSID_START, 0,
|
||||
REPEATER_BSSID_MAX - REPEATER_BSSID_START);
|
||||
@ -295,15 +304,6 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (dev->pm.enable) {
|
||||
ret = mt7921_mcu_set_bss_pm(dev, vif, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
}
|
||||
|
||||
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
|
||||
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
@ -318,6 +318,8 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
mt7921_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
ewma_rssi_init(&mvif->rssi);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
@ -348,19 +350,12 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
|
||||
if (vif == phy->monitor_vif)
|
||||
phy->monitor_vif = NULL;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
|
||||
|
||||
if (dev->pm.enable) {
|
||||
mt7921_mcu_set_bss_pm(dev, vif, false);
|
||||
mt76_clear(dev, MT_WF_RFCR(0),
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
}
|
||||
|
||||
mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
|
||||
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
|
||||
mt7921_mutex_release(dev);
|
||||
@ -413,7 +408,8 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv :
|
||||
&mvif->sta;
|
||||
struct mt76_wcid *wcid = &msta->wcid;
|
||||
int idx = key->keyidx;
|
||||
u8 *wcid_keyidx = &wcid->hw_key_idx;
|
||||
int idx = key->keyidx, err = 0;
|
||||
|
||||
/* The hardware does not support per-STA RX GTK, fallback
|
||||
* to software mode for these.
|
||||
@ -429,6 +425,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
|
||||
wcid_keyidx = &wcid->hw_key_idx2;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
@ -443,23 +440,29 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
key->hw_key_idx = wcid->idx;
|
||||
wcid->hw_key_idx = idx;
|
||||
} else if (idx == wcid->hw_key_idx) {
|
||||
wcid->hw_key_idx = -1;
|
||||
}
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
if (cmd == SET_KEY)
|
||||
*wcid_keyidx = idx;
|
||||
else if (idx == *wcid_keyidx)
|
||||
*wcid_keyidx = -1;
|
||||
else
|
||||
goto out;
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
||||
cmd == SET_KEY ? key : NULL);
|
||||
|
||||
return mt7921_mcu_add_key(dev, vif, msta, key, cmd);
|
||||
err = mt7921_mcu_add_key(dev, vif, msta, key, cmd);
|
||||
out:
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
bool band = phy != &dev->phy;
|
||||
int ret;
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
@ -480,9 +483,9 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
||||
else
|
||||
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
|
||||
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN,
|
||||
enabled);
|
||||
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
|
||||
mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
|
||||
}
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
@ -511,7 +514,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
bool band = phy != &dev->phy;
|
||||
u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
|
||||
MT_WF_RFCR1_DROP_BF_POLL |
|
||||
MT_WF_RFCR1_DROP_BA |
|
||||
@ -551,16 +553,46 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
||||
MT_WF_RFCR_DROP_NDPA);
|
||||
|
||||
*total_flags = flags;
|
||||
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
|
||||
mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
|
||||
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
|
||||
mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags);
|
||||
else
|
||||
mt76_set(dev, MT_WF_RFCR1(band), ctl_flags);
|
||||
mt76_set(dev, MT_WF_RFCR1(0), ctl_flags);
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_bss_bcnft_apply(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool assoc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev->pm.enable)
|
||||
return 0;
|
||||
|
||||
if (assoc) {
|
||||
ret = mt7921_mcu_uni_bss_bcnft(dev, vif, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = mt7921_mcu_set_bss_pm(dev, vif, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
|
||||
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info,
|
||||
@ -587,6 +619,12 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & BSS_CHANGED_PS)
|
||||
mt7921_mcu_uni_bss_ps(dev, vif);
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC)
|
||||
mt7921_bss_bcnft_apply(dev, vif, info->assoc);
|
||||
|
||||
if (changed & BSS_CHANGED_ARP_FILTER)
|
||||
mt7921_mcu_update_arp_filter(hw, vif, info);
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
@ -596,6 +634,15 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
int rssi = -ewma_rssi_read(&mvif->rssi);
|
||||
struct mt76_sta_cmd_info info = {
|
||||
.sta = sta,
|
||||
.vif = vif,
|
||||
.enable = true,
|
||||
.cmd = MCU_UNI_CMD_STA_REC_UPDATE,
|
||||
.wcid = &msta->wcid,
|
||||
.rcpi = to_rcpi(rssi),
|
||||
};
|
||||
int ret, idx;
|
||||
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
|
||||
@ -622,8 +669,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
mt7921_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
ret = mt76_connac_mcu_add_sta_cmd(&dev->mphy, vif, sta, &msta->wcid,
|
||||
true, MCU_UNI_CMD_STA_REC_UPDATE);
|
||||
ret = mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -637,21 +683,28 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
|
||||
struct mt76_sta_cmd_info info = {
|
||||
.sta = sta,
|
||||
.vif = vif,
|
||||
.cmd = MCU_UNI_CMD_STA_REC_UPDATE,
|
||||
.wcid = &msta->wcid,
|
||||
};
|
||||
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
|
||||
mt76_connac_pm_wake(&dev->mphy, &dev->pm);
|
||||
|
||||
mt76_connac_mcu_add_sta_cmd(&dev->mphy, vif, sta, &msta->wcid, false,
|
||||
MCU_UNI_CMD_STA_REC_UPDATE);
|
||||
mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
|
||||
|
||||
mt7921_mac_wtbl_update(dev, msta->wcid.idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
|
||||
false);
|
||||
ewma_rssi_init(&mvif->rssi);
|
||||
if (!sta->tdls)
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
|
||||
&mvif->sta.wcid, false);
|
||||
}
|
||||
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
@ -814,11 +867,17 @@ mt7921_get_stats(struct ieee80211_hw *hw,
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
struct mib_stats *mib = &phy->mib;
|
||||
|
||||
mt7921_mutex_acquire(phy->dev);
|
||||
|
||||
stats->dot11RTSSuccessCount = mib->rts_cnt;
|
||||
stats->dot11RTSFailureCount = mib->rts_retries_cnt;
|
||||
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
|
||||
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
|
||||
|
||||
memset(mib, 0, sizeof(*mib));
|
||||
|
||||
mt7921_mutex_release(phy->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -827,9 +886,7 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
u8 omac_idx = mvif->mt76.omac_idx;
|
||||
bool band = phy != &dev->phy;
|
||||
union {
|
||||
u64 t64;
|
||||
u32 t32[2];
|
||||
@ -840,9 +897,9 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
|
||||
n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;
|
||||
/* TSF software read */
|
||||
mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE);
|
||||
tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
|
||||
tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
|
||||
mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE);
|
||||
tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0));
|
||||
tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0));
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
@ -855,9 +912,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
u8 omac_idx = mvif->mt76.omac_idx;
|
||||
bool band = phy != &dev->phy;
|
||||
union {
|
||||
u64 t64;
|
||||
u32 t32[2];
|
||||
@ -867,10 +922,10 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;
|
||||
mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
|
||||
mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
|
||||
mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]);
|
||||
mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]);
|
||||
/* TSF software overwrite */
|
||||
mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_WRITE);
|
||||
mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE);
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
@ -1008,14 +1063,6 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 changed)
|
||||
{
|
||||
}
|
||||
|
||||
static void mt7921_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@ -1120,6 +1167,15 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw,
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u32 queues, bool drop)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy),
|
||||
HZ / 2);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7921_ops = {
|
||||
.tx = mt7921_tx,
|
||||
.start = mt7921_start,
|
||||
@ -1133,7 +1189,6 @@ const struct ieee80211_ops mt7921_ops = {
|
||||
.sta_add = mt7921_sta_add,
|
||||
.sta_remove = mt7921_sta_remove,
|
||||
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
|
||||
.sta_rc_update = mt7921_sta_rc_update,
|
||||
.set_key = mt7921_set_key,
|
||||
.ampdu_action = mt7921_ampdu_action,
|
||||
.set_rts_threshold = mt7921_set_rts_threshold,
|
||||
@ -1158,4 +1213,5 @@ const struct ieee80211_ops mt7921_ops = {
|
||||
.set_wakeup = mt7921_set_wakeup,
|
||||
.set_rekey_data = mt7921_set_rekey_data,
|
||||
#endif /* CONFIG_PM */
|
||||
.flush = mt7921_flush,
|
||||
};
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/fs.h>
|
||||
#include "mt7921.h"
|
||||
#include "mt7921_trace.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
@ -222,8 +223,16 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
u32 val;
|
||||
u8 seq;
|
||||
|
||||
/* TODO: make dynamic based on msg type */
|
||||
mdev->mcu.timeout = 20 * HZ;
|
||||
switch (cmd) {
|
||||
case MCU_UNI_CMD_HIF_CTRL:
|
||||
case MCU_UNI_CMD_SUSPEND:
|
||||
case MCU_UNI_CMD_OFFLOAD:
|
||||
mdev->mcu.timeout = HZ / 3;
|
||||
break;
|
||||
default:
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
break;
|
||||
}
|
||||
|
||||
seq = ++dev->mt76.mcu.msg_seq & 0xf;
|
||||
if (!seq)
|
||||
@ -404,9 +413,12 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
|
||||
|
||||
if (wlan_idx >= MT76_N_WCIDS)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
|
||||
if (!wcid)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
msta = container_of(wcid, struct mt7921_sta, wcid);
|
||||
stats = &msta->stats;
|
||||
@ -414,6 +426,8 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
|
||||
/* current rate */
|
||||
mt7921_mcu_tx_rate_parse(mphy, &peer, &rate, curr);
|
||||
stats->tx_rate = rate;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -466,30 +480,42 @@ mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
static void
|
||||
mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data;
|
||||
struct debug_msg {
|
||||
struct mt7921_debug_msg {
|
||||
__le16 id;
|
||||
u8 type;
|
||||
u8 flag;
|
||||
__le32 value;
|
||||
__le16 len;
|
||||
u8 content[512];
|
||||
} __packed * debug_msg;
|
||||
u16 cur_len;
|
||||
} __packed * msg;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
msg = (struct mt7921_debug_msg *)skb->data;
|
||||
|
||||
if (msg->type == 3) { /* fw log */
|
||||
u16 len = min_t(u16, le16_to_cpu(msg->len), 512);
|
||||
int i;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
debug_msg = (struct debug_msg *)skb->data;
|
||||
|
||||
cur_len = min_t(u16, le16_to_cpu(debug_msg->len), 512);
|
||||
|
||||
if (debug_msg->type == 0x3) {
|
||||
for (i = 0 ; i < cur_len; i++)
|
||||
if (!debug_msg->content[i])
|
||||
debug_msg->content[i] = ' ';
|
||||
|
||||
dev_dbg(dev->mt76.dev, "%s", debug_msg->content);
|
||||
for (i = 0 ; i < len; i++) {
|
||||
if (!msg->content[i])
|
||||
msg->content[i] = ' ';
|
||||
}
|
||||
wiphy_info(mt76_hw(dev)->wiphy, "%*s", len, msg->content);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_mcu_lp_event {
|
||||
u8 state;
|
||||
u8 reserved[3];
|
||||
} __packed * event;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
|
||||
event = (struct mt7921_mcu_lp_event *)skb->data;
|
||||
|
||||
trace_lp_event(dev, event->state);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -515,6 +541,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
mt76_connac_mcu_coredump_event(&dev->mt76, skb,
|
||||
&dev->coredump);
|
||||
return;
|
||||
case MCU_EVENT_LP_INFO:
|
||||
mt7921_mcu_low_power_event(dev, skb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -537,6 +566,7 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
rxd->eid == MCU_EVENT_SCAN_DONE ||
|
||||
rxd->eid == MCU_EVENT_DBG_MSG ||
|
||||
rxd->eid == MCU_EVENT_COREDUMP ||
|
||||
rxd->eid == MCU_EVENT_LP_INFO ||
|
||||
!rxd->seq)
|
||||
mt7921_mcu_rx_unsolicited_event(dev, skb);
|
||||
else
|
||||
@ -919,25 +949,17 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl)
|
||||
sizeof(data), false);
|
||||
}
|
||||
|
||||
int mt7921_mcu_init(struct mt7921_dev *dev)
|
||||
int mt7921_run_firmware(struct mt7921_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7921_mcu_ops = {
|
||||
.headroom = sizeof(struct mt7921_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7921_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt7921_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
dev->mt76.mcu_ops = &mt7921_mcu_ops;
|
||||
err = mt7921_driver_own(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ret = mt7921_driver_own(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7921_load_firmware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
err = mt7921_load_firmware(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
|
||||
mt7921_mcu_fw_log_2_host(dev, 1);
|
||||
@ -945,20 +967,24 @@ int mt7921_mcu_init(struct mt7921_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921_mcu_init(struct mt7921_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7921_mcu_ops = {
|
||||
.headroom = sizeof(struct mt7921_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7921_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt7921_mcu_restart,
|
||||
.mcu_reset = mt7921_reset,
|
||||
};
|
||||
|
||||
dev->mt76.mcu_ops = &mt7921_mcu_ops;
|
||||
|
||||
return mt7921_run_firmware(dev);
|
||||
}
|
||||
|
||||
void mt7921_mcu_exit(struct mt7921_dev *dev)
|
||||
{
|
||||
u32 reg = mt7921_reg_map_l1(dev, MT_TOP_MISC);
|
||||
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE,
|
||||
FIELD_PREP(MT_TOP_MISC_FW_STATE,
|
||||
FW_STATE_FW_DOWNLOAD), 1000)) {
|
||||
dev_err(dev->mt76.dev, "Failed to exit mcu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0);
|
||||
mt76_wr(dev, reg, MT_TOP_LPCR_HOST_FW_OWN);
|
||||
mt7921_wfsys_reset(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
|
||||
@ -1255,6 +1281,7 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
|
||||
|
||||
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
|
||||
dev_err(dev->mt76.dev, "driver own failed\n");
|
||||
mt7921_reset(&dev->mt76);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -1281,6 +1308,7 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
|
||||
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
|
||||
dev_err(dev->mt76.dev, "firmware own failed\n");
|
||||
mt7921_reset(&dev->mt76);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -1292,8 +1320,14 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_phy *phy = priv;
|
||||
struct mt7921_dev *dev = phy->dev;
|
||||
int ret;
|
||||
|
||||
if (mt7921_mcu_set_bss_pm(dev, vif, dev->pm.enable))
|
||||
if (dev->pm.enable)
|
||||
ret = mt7921_mcu_uni_bss_bcnft(dev, vif, true);
|
||||
else
|
||||
ret = mt7921_mcu_set_bss_pm(dev, vif, false);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (dev->pm.enable) {
|
||||
@ -1304,3 +1338,47 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
}
|
||||
}
|
||||
|
||||
int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct sk_buff *skb;
|
||||
int i, len = min_t(int, info->arp_addr_cnt,
|
||||
IEEE80211_BSS_ARP_ADDR_LIST_LEN);
|
||||
struct {
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct mt76_connac_arpns_tlv arp;
|
||||
} req_hdr = {
|
||||
.hdr = {
|
||||
.bss_idx = mvif->mt76.idx,
|
||||
},
|
||||
.arp = {
|
||||
.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP),
|
||||
.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),
|
||||
.ips_num = len,
|
||||
.mode = 2, /* update */
|
||||
.option = 1,
|
||||
},
|
||||
};
|
||||
|
||||
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
|
||||
sizeof(req_hdr) + len * sizeof(__be32));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_put_data(skb, &req_hdr, sizeof(req_hdr));
|
||||
for (i = 0; i < len; i++) {
|
||||
u8 *addr = (u8 *)skb_put(skb, sizeof(__be32));
|
||||
|
||||
memcpy(addr, &info->arp_addr_list[i], sizeof(__be32));
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD,
|
||||
true);
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ struct mt7921_uni_txd {
|
||||
/* event table */
|
||||
enum {
|
||||
MCU_EVENT_REG_ACCESS = 0x05,
|
||||
MCU_EVENT_LP_INFO = 0x07,
|
||||
MCU_EVENT_SCAN_DONE = 0x0d,
|
||||
MCU_EVENT_BSS_ABSENCE = 0x11,
|
||||
MCU_EVENT_BSS_BEACON_LOSS = 0x13,
|
||||
@ -177,25 +178,6 @@ enum {
|
||||
MCU_PHY_STATE_OFDMLQ_CNINFO,
|
||||
};
|
||||
|
||||
#define STA_TYPE_STA BIT(0)
|
||||
#define STA_TYPE_AP BIT(1)
|
||||
#define STA_TYPE_ADHOC BIT(2)
|
||||
#define STA_TYPE_WDS BIT(4)
|
||||
#define STA_TYPE_BC BIT(5)
|
||||
|
||||
#define NETWORK_INFRA BIT(16)
|
||||
#define NETWORK_P2P BIT(17)
|
||||
#define NETWORK_IBSS BIT(18)
|
||||
#define NETWORK_WDS BIT(21)
|
||||
|
||||
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
|
||||
#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
|
||||
#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
|
||||
#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P)
|
||||
#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS)
|
||||
#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS)
|
||||
#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA)
|
||||
|
||||
struct sec_key {
|
||||
u8 cipher_id;
|
||||
u8 cipher_len;
|
||||
@ -251,29 +233,6 @@ enum {
|
||||
MT_IBF = BIT(1) /* implicit beamforming */
|
||||
};
|
||||
|
||||
#define MT7921_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
|
||||
sizeof(struct wtbl_generic) + \
|
||||
sizeof(struct wtbl_rx) + \
|
||||
sizeof(struct wtbl_ht) + \
|
||||
sizeof(struct wtbl_vht) + \
|
||||
sizeof(struct wtbl_hdr_trans) +\
|
||||
sizeof(struct wtbl_ba) + \
|
||||
sizeof(struct wtbl_smps))
|
||||
|
||||
#define MT7921_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct sta_rec_basic) + \
|
||||
sizeof(struct sta_rec_ht) + \
|
||||
sizeof(struct sta_rec_he) + \
|
||||
sizeof(struct sta_rec_ba) + \
|
||||
sizeof(struct sta_rec_vht) + \
|
||||
sizeof(struct sta_rec_uapsd) + \
|
||||
sizeof(struct sta_rec_amsdu) + \
|
||||
sizeof(struct tlv) + \
|
||||
MT7921_WTBL_UPDATE_MAX_SIZE)
|
||||
|
||||
#define MT7921_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
|
||||
sizeof(struct wtbl_ba))
|
||||
|
||||
#define STA_CAP_WMM BIT(0)
|
||||
#define STA_CAP_SGI_20 BIT(4)
|
||||
#define STA_CAP_SGI_40 BIT(5)
|
||||
|
@ -46,6 +46,9 @@
|
||||
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
|
||||
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)
|
||||
|
||||
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
|
||||
#define to_rcpi(rssi) (2 * (rssi) + 220)
|
||||
|
||||
struct mt7921_vif;
|
||||
struct mt7921_sta;
|
||||
|
||||
@ -92,21 +95,25 @@ struct mt7921_sta {
|
||||
struct mt7921_sta_key_conf bip;
|
||||
};
|
||||
|
||||
DECLARE_EWMA(rssi, 10, 8);
|
||||
|
||||
struct mt7921_vif {
|
||||
struct mt76_vif mt76; /* must be first */
|
||||
|
||||
struct mt7921_sta sta;
|
||||
struct mt7921_phy *phy;
|
||||
|
||||
struct ewma_rssi rssi;
|
||||
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
};
|
||||
|
||||
struct mib_stats {
|
||||
u16 ack_fail_cnt;
|
||||
u16 fcs_err_cnt;
|
||||
u16 rts_cnt;
|
||||
u16 rts_retries_cnt;
|
||||
u16 ba_miss_cnt;
|
||||
u32 ack_fail_cnt;
|
||||
u32 fcs_err_cnt;
|
||||
u32 rts_cnt;
|
||||
u32 rts_retries_cnt;
|
||||
u32 ba_miss_cnt;
|
||||
};
|
||||
|
||||
struct mt7921_phy {
|
||||
@ -125,7 +132,7 @@ struct mt7921_phy {
|
||||
s16 coverage_class;
|
||||
u8 slottime;
|
||||
|
||||
__le32 rx_ampdu_ts;
|
||||
u32 rx_ampdu_ts;
|
||||
u32 ampdu_ref;
|
||||
|
||||
struct mib_stats mib;
|
||||
@ -151,8 +158,6 @@ struct mt7921_dev {
|
||||
|
||||
struct work_struct init_work;
|
||||
struct work_struct reset_work;
|
||||
wait_queue_head_t reset_wait;
|
||||
u32 reset_state;
|
||||
|
||||
struct list_head sta_poll_list;
|
||||
spinlock_t sta_poll_lock;
|
||||
@ -209,6 +214,7 @@ extern struct pci_driver mt7921_pci_driver;
|
||||
|
||||
u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
|
||||
|
||||
int __mt7921_start(struct mt7921_phy *phy);
|
||||
int mt7921_register_device(struct mt7921_dev *dev);
|
||||
void mt7921_unregister_device(struct mt7921_dev *dev);
|
||||
int mt7921_eeprom_init(struct mt7921_dev *dev);
|
||||
@ -220,6 +226,7 @@ void mt7921_eeprom_init_sku(struct mt7921_dev *dev);
|
||||
int mt7921_dma_init(struct mt7921_dev *dev);
|
||||
void mt7921_dma_prefetch(struct mt7921_dev *dev);
|
||||
void mt7921_dma_cleanup(struct mt7921_dev *dev);
|
||||
int mt7921_run_firmware(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_init(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_add_bss_info(struct mt7921_phy *phy,
|
||||
struct ieee80211_vif *vif, int enable);
|
||||
@ -281,6 +288,7 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val)
|
||||
#define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
|
||||
#define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0)
|
||||
|
||||
void mt7921_mac_init(struct mt7921_dev *dev);
|
||||
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
|
||||
void mt7921_mac_reset_counters(struct mt7921_phy *phy);
|
||||
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
|
||||
@ -296,6 +304,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt7921_mac_work(struct work_struct *work);
|
||||
void mt7921_mac_reset_work(struct work_struct *work);
|
||||
void mt7921_reset(struct mt76_dev *mdev);
|
||||
int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
@ -339,4 +348,8 @@ int mt7921_mac_set_beacon_filter(struct mt7921_phy *phy,
|
||||
bool enable);
|
||||
void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
|
||||
void mt7921_coredump_work(struct work_struct *work);
|
||||
int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info);
|
||||
int mt7921_wfsys_reset(struct mt7921_dev *dev);
|
||||
#endif
|
||||
|
51
drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h
Normal file
51
drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/*
|
||||
* Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
|
||||
#if !defined(__MT7921_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define __MT7921_TRACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include "mt7921.h"
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM mt7921
|
||||
|
||||
#define MAXNAME 32
|
||||
#define DEV_ENTRY __array(char, wiphy_name, 32)
|
||||
#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \
|
||||
wiphy_name(mt76_hw(dev)->wiphy), MAXNAME)
|
||||
#define DEV_PR_FMT "%s"
|
||||
#define DEV_PR_ARG __entry->wiphy_name
|
||||
#define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready"
|
||||
|
||||
TRACE_EVENT(lp_event,
|
||||
TP_PROTO(struct mt7921_dev *dev, u8 lp_state),
|
||||
|
||||
TP_ARGS(dev, lp_state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
DEV_ENTRY
|
||||
__field(u8, lp_state)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
DEV_ASSIGN;
|
||||
__entry->lp_state = lp_state;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
DEV_PR_FMT " %s",
|
||||
DEV_PR_ARG, LP_STATE_PR_ARG
|
||||
)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE mt7921_trace
|
||||
|
||||
#include <trace/define_trace.h>
|
@ -13,7 +13,7 @@
|
||||
#include "../trace.h"
|
||||
|
||||
static const struct pci_device_id mt7921_pci_device_table[] = {
|
||||
{ PCI_DEVICE(0x14c3, 0x7961) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961) },
|
||||
{ },
|
||||
};
|
||||
|
||||
@ -137,7 +137,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
|
||||
|
||||
mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
|
||||
ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||
@ -146,10 +146,12 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
ret = mt7921_register_device(dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
goto err_free_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
devm_free_irq(&pdev->dev, pdev->irq, dev);
|
||||
err_free_dev:
|
||||
mt76_free_device(&dev->mt76);
|
||||
err_free_pci_vec:
|
||||
@ -209,12 +211,12 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
/* disable interrupt */
|
||||
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
|
||||
|
||||
pci_save_state(pdev);
|
||||
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
err = mt7921_mcu_fw_pmctrl(dev);
|
||||
if (err)
|
||||
goto restore;
|
||||
|
||||
err = mt7921_mcu_drv_pmctrl(dev);
|
||||
pci_save_state(pdev);
|
||||
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
if (err)
|
||||
goto restore;
|
||||
|
||||
@ -237,18 +239,18 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
int i, err;
|
||||
|
||||
err = mt7921_mcu_fw_pmctrl(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = pci_set_power_state(pdev, PCI_D0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pci_restore_state(pdev);
|
||||
|
||||
err = mt7921_mcu_drv_pmctrl(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* enable interrupt */
|
||||
mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
|
||||
|
@ -96,8 +96,8 @@
|
||||
#define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800)
|
||||
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
|
||||
|
||||
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014)
|
||||
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698)
|
||||
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16)
|
||||
|
||||
#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
|
||||
#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
|
||||
@ -121,16 +121,21 @@
|
||||
#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16)
|
||||
#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, 0x104 + ((n) << 4))
|
||||
#define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16)
|
||||
#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688)
|
||||
#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690)
|
||||
#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518)
|
||||
#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520)
|
||||
#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4))
|
||||
#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0)
|
||||
|
||||
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2))
|
||||
#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2))
|
||||
#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2))
|
||||
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2))
|
||||
#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2))
|
||||
#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2))
|
||||
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0))
|
||||
|
||||
#define MT_WTBLON_TOP_BASE 0x34000
|
||||
@ -357,11 +362,11 @@
|
||||
#define MT_INFRA_CFG_BASE 0xfe000
|
||||
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
|
||||
|
||||
#define MT_HIF_REMAP_L1 MT_INFRA(0x260)
|
||||
#define MT_HIF_REMAP_L1 MT_INFRA(0x24c)
|
||||
#define MT_HIF_REMAP_L1_MASK GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_BASE_L1 0xe0000
|
||||
#define MT_HIF_REMAP_BASE_L1 0x40000
|
||||
|
||||
#define MT_SWDEF_BASE 0x41f200
|
||||
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
|
||||
@ -380,11 +385,17 @@
|
||||
#define MT_TOP_MISC MT_TOP(0xf0)
|
||||
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
|
||||
|
||||
#define MT_MCU_WPDMA0_BASE 0x54000000
|
||||
#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs))
|
||||
|
||||
#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120)
|
||||
#define MT_WFDMA_NEED_REINIT BIT(1)
|
||||
|
||||
#define MT_HW_BOUND 0x70010020
|
||||
#define MT_HW_CHIPID 0x70010200
|
||||
#define MT_HW_REV 0x70010204
|
||||
|
||||
#define MT_PCIE_MAC_BASE 0x74030000
|
||||
#define MT_PCIE_MAC_BASE 0x10000
|
||||
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
|
||||
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
|
||||
|
||||
@ -413,6 +424,10 @@
|
||||
#define PCIE_LPCR_HOST_CLR_OWN BIT(1)
|
||||
#define PCIE_LPCR_HOST_SET_OWN BIT(0)
|
||||
|
||||
#define MT_WFSYS_SW_RST_B 0x18000140
|
||||
#define WFSYS_SW_RST_B BIT(0)
|
||||
#define WFSYS_SW_INIT_DONE BIT(4)
|
||||
|
||||
#define MT_CONN_ON_MISC 0x7c0600f0
|
||||
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
|
||||
|
||||
|
12
drivers/net/wireless/mediatek/mt76/mt7921/trace.c
Normal file
12
drivers/net/wireless/mediatek/mt76/mt7921/trace.c
Normal file
@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#ifndef __CHECKER__
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "mt7921_trace.h"
|
||||
|
||||
#endif
|
@ -256,6 +256,9 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
|
||||
q->entry[q->head].skb = tx_info.skb;
|
||||
q->entry[q->head].buf_sz = len;
|
||||
|
||||
smp_wmb();
|
||||
|
||||
q->head = (q->head + 1) % q->ndesc;
|
||||
q->queued++;
|
||||
|
||||
|
@ -461,11 +461,11 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
int ret = 0;
|
||||
|
||||
while (1) {
|
||||
int n_frames = 0;
|
||||
|
||||
if (test_bit(MT76_STATE_PM, &phy->state) ||
|
||||
test_bit(MT76_RESET, &phy->state)) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
test_bit(MT76_RESET, &phy->state))
|
||||
return -EBUSY;
|
||||
|
||||
if (dev->queue_ops->tx_cleanup &&
|
||||
q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) {
|
||||
@ -497,11 +497,16 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
}
|
||||
|
||||
if (!mt76_txq_stopped(q))
|
||||
ret += mt76_txq_send_burst(phy, q, mtxq);
|
||||
n_frames = mt76_txq_send_burst(phy, q, mtxq);
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
|
||||
ieee80211_return_txq(phy->hw, txq, false);
|
||||
|
||||
if (unlikely(n_frames < 0))
|
||||
return n_frames;
|
||||
|
||||
ret += n_frames;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user