From c15b0f7cd0b9f35adfce838e6656d597f0733c05 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 1 May 2019 15:44:25 +0200 Subject: [PATCH 01/69] mt76: mt76x02: remove useless return in mt76x02_resync_beacon_timer Remove useless return statment in mt76x02_resync_beacon_timer routine Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index e196b9c0a6861..d61c686e08de7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -189,10 +189,8 @@ mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) mt76_rmw_field(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_INTVAL, timer_val); - if (dev->tbtt_count >= 64) { + if (dev->tbtt_count >= 64) dev->tbtt_count = 0; - return; - } } EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer); From 8402650aa708a3e4f35ded7bcfb47da516a2f6e8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 1 May 2019 16:06:20 +0200 Subject: [PATCH 02/69] mt76: move tx_napi in mt76_dev Move tx_napi in mt76_dev data structure in order to implement concurrency between tx scheduling and tx cleanup in mt7603 and mt7615 drivers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 - .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 19 ++++++++++--------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8ecbf81a906f5..fc4169c83e764 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -452,6 +452,7 @@ struct mt76_dev { int tx_dma_idx[4]; struct tasklet_struct tx_tasklet; + struct napi_struct tx_napi; struct delayed_work mac_work; wait_queue_head_t tx_wait; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 687bd14b2d776..f7fd53a1738a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -90,7 +90,6 @@ struct mt76x02_dev { struct sk_buff *rx_head; - struct napi_struct tx_napi; struct delayed_work cal_work; struct delayed_work wdt_work; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 7b7163bc3b623..617934565818c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -166,7 +166,8 @@ static void mt76x02_tx_tasklet(unsigned long data) static int mt76x02_poll_tx(struct napi_struct *napi, int budget) { - struct mt76x02_dev *dev = container_of(napi, struct mt76x02_dev, tx_napi); + struct mt76x02_dev *dev = container_of(napi, struct mt76x02_dev, + mt76.tx_napi); int i; mt76x02_mac_poll_tx_status(dev, false); @@ -245,9 +246,9 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->tx_napi, mt76x02_poll_tx, - NAPI_POLL_WEIGHT); - napi_enable(&dev->tx_napi); + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt76x02_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); return 0; } @@ -303,7 +304,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) if (intr & (MT_INT_TX_STAT | MT_INT_TX_DONE_ALL)) { mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL); - napi_schedule(&dev->tx_napi); + napi_schedule(&dev->mt76.tx_napi); } if (intr & MT_INT_GPTIMER) { @@ -334,7 +335,7 @@ static void mt76x02_dma_enable(struct mt76x02_dev *dev) void mt76x02_dma_cleanup(struct mt76x02_dev *dev) { tasklet_kill(&dev->mt76.tx_tasklet); - netif_napi_del(&dev->tx_napi); + netif_napi_del(&dev->mt76.tx_napi); mt76_dma_cleanup(&dev->mt76); } EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup); @@ -454,7 +455,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) tasklet_disable(&dev->mt76.pre_tbtt_tasklet); tasklet_disable(&dev->mt76.tx_tasklet); - napi_disable(&dev->tx_napi); + napi_disable(&dev->mt76.tx_napi); for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) napi_disable(&dev->mt76.napi[i]); @@ -508,8 +509,8 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) clear_bit(MT76_RESET, &dev->mt76.state); tasklet_enable(&dev->mt76.tx_tasklet); - napi_enable(&dev->tx_napi); - napi_schedule(&dev->tx_napi); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); From 9e63f5e76b5638f51f50e7815914daf879af5b30 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 1 May 2019 16:06:21 +0200 Subject: [PATCH 03/69] mt76: mt7603: use napi polling for tx cleanup This allows tx scheduling and tx cleanup to run concurrently Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7603/core.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/dma.c | 30 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7603/mac.c | 4 ++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index 37e5644b45efa..e7ee58e3379c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -35,7 +35,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) if (intr & MT_INT_TX_DONE_ALL) { mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->mt76.tx_tasklet); + napi_schedule(&dev->mt76.tx_napi); } if (intr & MT_INT_RX_DONE(0)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 27e2d9f905533..54314f6803c5b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -139,15 +139,30 @@ static void mt7603_tx_tasklet(unsigned long data) { struct mt7603_dev *dev = (struct mt7603_dev *)data; + + mt76_txq_schedule_all(&dev->mt76); +} + +static int mt7603_poll_tx(struct napi_struct *napi, int budget) +{ + struct mt7603_dev *dev; int i; + dev = container_of(napi, struct mt7603_dev, mt76.tx_napi); dev->tx_dma_check = 0; + for (i = MT_TXQ_MCU; i >= 0; i--) mt76_queue_tx_cleanup(dev, i, false); - mt76_txq_schedule_all(&dev->mt76); + if (napi_complete_done(napi, 0)) + mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); - mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); + for (i = MT_TXQ_MCU; i >= 0; i--) + mt76_queue_tx_cleanup(dev, i, false); + + tasklet_schedule(&dev->mt76.tx_tasklet); + + return 0; } int mt7603_dma_init(struct mt7603_dev *dev) @@ -216,7 +231,15 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; mt76_wr(dev, MT_DELAY_INT_CFG, 0); - return mt76_init_queues(dev); + ret = mt76_init_queues(dev); + if (ret) + return ret; + + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt7603_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); + + return 0; } void mt7603_dma_cleanup(struct mt7603_dev *dev) @@ -227,5 +250,6 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev) MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); tasklet_kill(&dev->mt76.tx_tasklet); + netif_napi_del(&dev->mt76.tx_napi); mt76_dma_cleanup(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 6d506e34c3eeb..0ccba5926b684 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1282,6 +1282,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) tasklet_disable(&dev->mt76.pre_tbtt_tasklet); napi_disable(&dev->mt76.napi[0]); napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.tx_napi); mutex_lock(&dev->mt76.mutex); @@ -1326,7 +1327,8 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->mt76.tx_tasklet); - tasklet_schedule(&dev->mt76.tx_tasklet); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); mt7603_beacon_set_timer(dev, -1, beacon_int); From 8357f0dcd895231ca1444df60e57a1a33605e282 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 1 May 2019 16:06:22 +0200 Subject: [PATCH 04/69] mt76: mt7615: use napi polling for tx cleanup This allows tx scheduling and tx cleanup to run concurrently Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/dma.c | 24 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7615/pci.c | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 3ec6582afd8f5..9c565c93988a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -93,18 +93,33 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, static void mt7615_tx_tasklet(unsigned long data) { struct mt7615_dev *dev = (struct mt7615_dev *)data; + + mt76_txq_schedule_all(&dev->mt76); +} + +static int mt7615_poll_tx(struct napi_struct *napi, int budget) +{ static const u8 queue_map[] = { MT_TXQ_MCU, MT_TXQ_BE }; + struct mt7615_dev *dev; int i; + dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); + for (i = 0; i < ARRAY_SIZE(queue_map); i++) mt76_queue_tx_cleanup(dev, queue_map[i], false); - mt76_txq_schedule_all(&dev->mt76); + if (napi_complete_done(napi, 0)) + mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); - mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); + for (i = 0; i < ARRAY_SIZE(queue_map); i++) + mt76_queue_tx_cleanup(dev, queue_map[i], false); + + tasklet_schedule(&dev->mt76.tx_tasklet); + + return 0; } int mt7615_dma_init(struct mt7615_dev *dev) @@ -178,6 +193,10 @@ 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, + mt7615_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); + mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000); @@ -201,5 +220,6 @@ void mt7615_dma_cleanup(struct mt7615_dev *dev) mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); tasklet_kill(&dev->mt76.tx_tasklet); + netif_napi_del(&dev->mt76.tx_napi); mt76_dma_cleanup(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 11122bd2d7278..10a249e13a43c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -49,7 +49,7 @@ irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) if (intr & MT_INT_TX_DONE_ALL) { mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->mt76.tx_tasklet); + napi_schedule(&dev->mt76.tx_napi); } if (intr & MT_INT_RX_DONE(0)) { From 4875e34679ba259bb8fa6a3ac337d76c8b7283a9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 1 May 2019 16:06:23 +0200 Subject: [PATCH 05/69] mt76: move netif_napi_del in mt76_dma_cleanup Move netif_napi_del in mt76_dma_cleanup routine since it is done by all drivers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 1 + drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 1 - drivers/net/wireless/mediatek/mt76/mt7615/dma.c | 1 - drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 4381155375e1e..d8f61e540bfd3 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -588,6 +588,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) { int i; + netif_napi_del(&dev->tx_napi); for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) mt76_dma_tx_cleanup(dev, i, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 54314f6803c5b..58dc511f93c54 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -250,6 +250,5 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev) MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); tasklet_kill(&dev->mt76.tx_tasklet); - netif_napi_del(&dev->mt76.tx_napi); mt76_dma_cleanup(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 9c565c93988a8..6a70273d4a694 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -220,6 +220,5 @@ void mt7615_dma_cleanup(struct mt7615_dev *dev) mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); tasklet_kill(&dev->mt76.tx_tasklet); - netif_napi_del(&dev->mt76.tx_napi); mt76_dma_cleanup(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 617934565818c..467b283798704 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -335,7 +335,6 @@ static void mt76x02_dma_enable(struct mt76x02_dev *dev) void mt76x02_dma_cleanup(struct mt76x02_dev *dev) { tasklet_kill(&dev->mt76.tx_tasklet); - netif_napi_del(&dev->mt76.tx_napi); mt76_dma_cleanup(&dev->mt76); } EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup); From b1571a0e77d8cef14227af293c6dda1464a57270 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 3 May 2019 15:54:36 +0300 Subject: [PATCH 06/69] mt76: Fix a signedness bug in mt7615_add_interface() The problem is that "mvif->omac_idx" is a u8 so it can't be negative and the error handling won't work. The get_omac_idx() function returns -1 on error. Fixes: 04b8e65922f6 ("mt76: add mac80211 driver for MT7615 PCIe-based chipsets") Signed-off-by: Dan Carpenter Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 80e6b211f60b8..8d7a47d1b2055 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -77,11 +77,12 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, goto out; } - mvif->omac_idx = get_omac_idx(vif->type, dev->omac_mask); - if (mvif->omac_idx < 0) { + idx = get_omac_idx(vif->type, dev->omac_mask); + if (idx < 0) { ret = -ENOSPC; goto out; } + mvif->omac_idx = idx; /* TODO: DBDC support. Use band 0 and wmm 0 for now */ mvif->band_idx = 0; From 9db1aec0c2d72a3b7b115ba56e8dbb5b46855333 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 3 May 2019 16:09:13 +0300 Subject: [PATCH 07/69] mt76: mt7615: Use after free in mt7615_mcu_set_bcn() We dereference "skb" when we assign: req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); ^^^^^^^^ So this patch just moves the dev_kfree_skb() down a bit to avoid the use after free. Fixes: 04b8e65922f6 ("mt76: add mac80211 driver for MT7615 PCIe-based chipsets") Signed-off-by: Dan Carpenter Acked-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index ea67c6022fe6f..dc1301effa242 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1270,7 +1270,6 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, 0, NULL); memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); - dev_kfree_skb(skb); req.omac_idx = mvif->omac_idx; req.enable = en; @@ -1281,6 +1280,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + tim_off); + dev_kfree_skb(skb); skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, From fd5f65c552f703b61caa9cd5842f88b897dcc44c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 4 May 2019 18:22:47 +0800 Subject: [PATCH 08/69] mt76: mt7615: Make mt7615_irq_handler static Fix sparse warning: drivers/net/wireless/mediatek/mt76/mt7615/pci.c:37:13: warning: symbol 'mt7615_irq_handler' was not declared. Should it be static? Signed-off-by: YueHaibing Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 10a249e13a43c..e731b2bfa0291 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -34,7 +34,7 @@ void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); } -irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) +static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) { struct mt7615_dev *dev = dev_instance; u32 intr; From 8e309f7dc7e76fca1e7fa510e39618181f1f13b4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:53 +0200 Subject: [PATCH 09/69] mt7615: mcu: simplify __mt7615_mcu_set_wtbl Do not loop over cmd payload in __mt7615_mcu_set_wtbl since it is already done in before running __mt7615_mcu_set_wtbl (e.g. mt7615_mcu_set_wtbl_key) Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 62 ++++++++----------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index dc1301effa242..3de20c8111cf4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -918,37 +918,24 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, return __mt7615_mcu_set_bss_info(dev, &bss_info); } -static int __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, - int operation, void *buf, int buf_len) +static int +__mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, + int operation, int ntlv, void *buf, + int buf_len) { struct req_hdr { u8 wlan_idx; u8 operation; __le16 tlv_num; u8 rsv[4]; - } __packed req_hdr = {0}; - struct tlv { - __le16 tag; - __le16 len; - u8 buf[0]; - } __packed; + } __packed req_hdr = { + .wlan_idx = wlan_idx, + .operation = operation, + .tlv_num = cpu_to_le16(ntlv), + }; struct sk_buff *skb; - u16 tlv_num = 0; - int offset = 0; - - while (offset < buf_len) { - struct tlv *tlv = (struct tlv *)((u8 *)buf + offset); - - tlv_num++; - offset += tlv->len; - } skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); - - req_hdr.wlan_idx = wlan_idx; - req_hdr.operation = operation; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); if (buf && buf_len) @@ -1015,8 +1002,8 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, wtbl_sec_key.key_len = sizeof(wtbl_sec_key.key_material); } - return __mt7615_mcu_set_wtbl(dev, wcid, WTBL_SET, &wtbl_sec_key, - buf_len); + return __mt7615_mcu_set_wtbl(dev, wcid, WTBL_SET, 1, + &wtbl_sec_key, buf_len); } int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) @@ -1047,7 +1034,8 @@ int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) wtbl_rx->rv = 1; ret = __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, buf, buf_len); + WTBL_RESET_AND_SET, 2, buf, + buf_len); kfree(buf); return ret; @@ -1058,7 +1046,7 @@ int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, NULL, 0); + WTBL_RESET_AND_SET, 0, NULL, 0); } int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -1092,8 +1080,8 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_rx->rca2 = 1; wtbl_rx->rv = 1; - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, - WTBL_RESET_AND_SET, buf, buf_len); + ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_RESET_AND_SET, + 2, buf, buf_len); kfree(buf); return ret; @@ -1105,12 +1093,12 @@ int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, - WTBL_RESET_AND_SET, NULL, 0); + WTBL_RESET_AND_SET, 0, NULL, 0); } int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) { - return __mt7615_mcu_set_wtbl(dev, 0, WTBL_RESET_ALL, NULL, 0); + return __mt7615_mcu_set_wtbl(dev, 0, WTBL_RESET_ALL, 0, NULL, 0); } static int __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, @@ -1367,7 +1355,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct wtbl_ht *wtbl_ht; struct wtbl_raw *wtbl_raw; struct sta_rec_ht *sta_rec_ht; - int buf_len, ret; + int buf_len, ret, ntlv = 2; u32 msk, val = 0; u8 *buf; @@ -1400,6 +1388,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); wtbl_vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC; wtbl_vht->vht = 1; + ntlv++; if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) val |= MT_WTBL_W5_SHORT_GI_80; @@ -1416,6 +1405,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); wtbl_smps->smps = 1; + ntlv++; } /* sgi */ @@ -1431,8 +1421,8 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_raw->msk = cpu_to_le32(~msk); wtbl_raw->val = cpu_to_le32(val); - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, buf, - buf_len); + ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, ntlv, + buf, buf_len); if (ret) { kfree(buf); return ret; @@ -1501,8 +1491,8 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, wtbl_ba.ba_winsize_idx = idx; } - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, &wtbl_ba, - buf_len); + ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, 1, + &wtbl_ba, buf_len); if (ret) return ret; @@ -1561,7 +1551,7 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, wtbl_ba.rst_ba_sb = 1; return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, - &wtbl_ba, buf_len); + 1, &wtbl_ba, buf_len); } void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, From 0467448d2eeaa6e58a95b18077eb4ae3877116b2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:54 +0200 Subject: [PATCH 10/69] mt7615: mcu: simplify __mt7615_mcu_set_sta_rec Do not loop over cmd payload in __mt7615_mcu_set_sta_rec since it is already done in before running __mt7615_mcu_set_sta_rec (e.g. mt7615_mcu_set_sta_rec) Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 3de20c8111cf4..2a632c0debe97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1101,9 +1101,10 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) return __mt7615_mcu_set_wtbl(dev, 0, WTBL_RESET_ALL, 0, NULL, 0); } -static int __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, - int wlan_idx, int muar_idx, void *buf, - int buf_len) +static int +__mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, + int wlan_idx, int muar_idx, int ntlv, + void *buf, int buf_len) { struct req_hdr { u8 bss_idx; @@ -1112,31 +1113,16 @@ static int __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, u8 is_tlv_append; u8 muar_idx; u8 rsv[2]; - } __packed req_hdr = {0}; - struct tlv { - __le16 tag; - __le16 len; - u8 buf[0]; - } __packed; + } __packed req_hdr = { + .bss_idx = bss_idx, + .wlan_idx = wlan_idx, + .tlv_num = cpu_to_le16(ntlv), + .is_tlv_append = !!ntlv, + .muar_idx = muar_idx, + }; struct sk_buff *skb; - u16 tlv_num = 0; - int offset = 0; - - while (offset < buf_len) { - struct tlv *tlv = (struct tlv *)((u8 *)buf + offset); - - tlv_num++; - offset += tlv->len; - } skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); - - req_hdr.bss_idx = bss_idx; - req_hdr.wlan_idx = wlan_idx; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - req_hdr.is_tlv_append = tlv_num ? 1 : 0; - req_hdr.muar_idx = muar_idx; - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); if (buf && buf_len) @@ -1167,7 +1153,7 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, } return __mt7615_mcu_set_sta_rec(dev, mvif->idx, mvif->sta.wcid.idx, - mvif->omac_idx, &sta_rec_basic, + mvif->omac_idx, 1, &sta_rec_basic, buf_len); } @@ -1216,7 +1202,7 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, } return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, &sta_rec_basic, + mvif->omac_idx, 1, &sta_rec_basic, buf_len); } @@ -1435,6 +1421,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, sta_rec_ht->tag = cpu_to_le16(STA_REC_HT); sta_rec_ht->len = cpu_to_le16(sizeof(*sta_rec_ht)); sta_rec_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + ntlv = 1; if (sta->vht_cap.vht_supported) { struct sta_rec_vht *sta_rec_vht; @@ -1448,10 +1435,12 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, cpu_to_le16(sta->vht_cap.vht_mcs.rx_mcs_map); sta_rec_vht->vht_tx_mcs_map = cpu_to_le16(sta->vht_cap.vht_mcs.tx_mcs_map); + ntlv++; } ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, buf, buf_len); + mvif->omac_idx, ntlv, buf, + buf_len); kfree(buf); return ret; } @@ -1508,7 +1497,8 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, sta_rec_ba.winsize = cpu_to_le16(ba_size); return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, &sta_rec_ba, buf_len); + mvif->omac_idx, 1, &sta_rec_ba, + buf_len); } int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, @@ -1535,7 +1525,8 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, sta_rec_ba.winsize = cpu_to_le16(params->buf_size); ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, &sta_rec_ba, buf_len); + mvif->omac_idx, 1, &sta_rec_ba, + buf_len); if (ret || !add) return ret; From b876457c6a40c109b5ad127805a4441f11e6e537 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:55 +0200 Subject: [PATCH 11/69] mt7615: mcu: remove bss_info_convert_vif_type routine Remove bss_info_convert_vif_type routine since it is run just in mt7615_mcu_set_bss_info and the switch over vif->type is already there. Simplify mt7615_mcu_set_bss_info routine Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 73 +++++++------------ 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 2a632c0debe97..2a73ac8b0d900 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -842,39 +842,28 @@ static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, MCU_Q_SET, MCU_S2D_H2N, NULL); } -static void bss_info_convert_vif_type(enum nl80211_iftype type, - u32 *network_type, u32 *conn_type) -{ - switch (type) { - case NL80211_IFTYPE_AP: - if (network_type) - *network_type = NETWORK_INFRA; - if (conn_type) - *conn_type = CONNECTION_INFRA_AP; - break; - case NL80211_IFTYPE_STATION: - if (network_type) - *network_type = NETWORK_INFRA; - if (conn_type) - *conn_type = CONNECTION_INFRA_STA; - break; - default: - WARN_ON(1); - break; - }; -} - -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en) +int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, int en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct bss_info bss_info = {0}; - u8 bmc_tx_wlan_idx = 0; - u32 network_type = 0, conn_type = 0; + struct bss_info bss_info = { + .bss_idx = mvif->idx, + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .bcn_interval = vif->bss_conf.beacon_int, + .dtim_period = vif->bss_conf.dtim_period, + .enable = en, + .feature = BIT(BSS_INFO_BASIC), + .wmm_idx = mvif->wmm_idx, + }; - if (vif->type == NL80211_IFTYPE_AP) { - bmc_tx_wlan_idx = mvif->sta.wcid.idx; - } else if (vif->type == NL80211_IFTYPE_STATION) { + switch (vif->type) { + case NL80211_IFTYPE_AP: + bss_info.bmc_tx_wlan_idx = mvif->sta.wcid.idx; + bss_info.network_type = NETWORK_INFRA; + bss_info.conn_type = CONNECTION_INFRA_AP; + break; + case NL80211_IFTYPE_STATION: { /* find the unicast entry for sta mode bmc tx */ struct ieee80211_sta *ap_sta; struct mt7615_sta *msta; @@ -888,27 +877,19 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, } msta = (struct mt7615_sta *)ap_sta->drv_priv; - bmc_tx_wlan_idx = msta->wcid.idx; + bss_info.bmc_tx_wlan_idx = msta->wcid.idx; + bss_info.network_type = NETWORK_INFRA; + bss_info.conn_type = CONNECTION_INFRA_STA; rcu_read_unlock(); - } else { + break; + } + default: WARN_ON(1); + break; } - - bss_info_convert_vif_type(vif->type, &network_type, &conn_type); - - bss_info.bss_idx = mvif->idx; memcpy(bss_info.bssid, vif->bss_conf.bssid, ETH_ALEN); - bss_info.omac_idx = mvif->omac_idx; - bss_info.band_idx = mvif->band_idx; - bss_info.bmc_tx_wlan_idx = bmc_tx_wlan_idx; - bss_info.wmm_idx = mvif->wmm_idx; - bss_info.network_type = network_type; - bss_info.conn_type = conn_type; - bss_info.bcn_interval = vif->bss_conf.beacon_int; - bss_info.dtim_period = vif->bss_conf.dtim_period; - bss_info.enable = en; - bss_info.feature = BIT(BSS_INFO_BASIC); + if (en) { bss_info.feature |= BIT(BSS_INFO_OMAC); if (mvif->omac_idx > EXT_BSSID_START) From 77eaa281c20e6227f4fdd73006e4ced113bd30b2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:56 +0200 Subject: [PATCH 12/69] mt7615: mcu: use proper msg size in mt7615_mcu_add_wtbl_bmc Use proper mcu message size in mt7615_mcu_add_wtbl_bmc and do not allocate a huge buffer. Moreover use stack memory instead of heap one Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 2a73ac8b0d900..ab72e34f5d0c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -987,39 +987,33 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, &wtbl_sec_key, buf_len); } -int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) +int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_generic *wtbl_generic; - struct wtbl_rx *wtbl_rx; - int buf_len, ret; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_generic = (struct wtbl_generic *)buf; - buf_len = sizeof(*wtbl_generic); - wtbl_generic->tag = cpu_to_le16(WTBL_GENERIC); - wtbl_generic->len = cpu_to_le16(buf_len); - eth_broadcast_addr(wtbl_generic->peer_addr); - wtbl_generic->muar_idx = 0xe; - - wtbl_rx = (struct wtbl_rx *)(buf + buf_len); - buf_len += sizeof(*wtbl_rx); - wtbl_rx->tag = cpu_to_le16(WTBL_RX); - wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); - wtbl_rx->rca1 = 1; - wtbl_rx->rca2 = 1; - wtbl_rx->rv = 1; - - ret = __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, 2, buf, - buf_len); + struct { + struct wtbl_generic g_wtbl; + struct wtbl_rx rx_wtbl; + } data = { + .g_wtbl = { + .tag = cpu_to_le16(WTBL_GENERIC), + .len = cpu_to_le16(sizeof(struct wtbl_generic)), + .muar_idx = 0xe, + }, + .rx_wtbl = { + .tag = cpu_to_le16(WTBL_RX), + .len = cpu_to_le16(sizeof(struct wtbl_rx)), + .rca1 = 1, + .rca2 = 1, + .rv = 1, + }, + }; + eth_broadcast_addr(data.g_wtbl.peer_addr); - kfree(buf); - return ret; + return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, + WTBL_RESET_AND_SET, 2, &data, + sizeof(struct wtbl_generic) + + sizeof(struct wtbl_rx)); } int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) From d7228bcf7b4e36956b9489139c194bf3678d19c1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:57 +0200 Subject: [PATCH 13/69] mt7615: mcu: use proper msg size in mt7615_mcu_add_wtbl Use proper mcu message size in mt7615_mcu_add_wtbl and do not allocate a huge buffer. Moreover use stack memory instead of heap one Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index ab72e34f5d0c5..2bda4830dbaf3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1029,37 +1029,31 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct wtbl_generic *wtbl_generic; - struct wtbl_rx *wtbl_rx; - int buf_len, ret; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_generic = (struct wtbl_generic *)buf; - buf_len = sizeof(*wtbl_generic); - wtbl_generic->tag = cpu_to_le16(WTBL_GENERIC); - wtbl_generic->len = cpu_to_le16(buf_len); - memcpy(wtbl_generic->peer_addr, sta->addr, ETH_ALEN); - wtbl_generic->muar_idx = mvif->omac_idx; - wtbl_generic->qos = sta->wme; - wtbl_generic->partial_aid = cpu_to_le16(sta->aid); - - wtbl_rx = (struct wtbl_rx *)(buf + buf_len); - buf_len += sizeof(*wtbl_rx); - wtbl_rx->tag = cpu_to_le16(WTBL_RX); - wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); - wtbl_rx->rca1 = (vif->type == NL80211_IFTYPE_AP) ? 0 : 1; - wtbl_rx->rca2 = 1; - wtbl_rx->rv = 1; - - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_RESET_AND_SET, - 2, buf, buf_len); + struct { + struct wtbl_generic g_wtbl; + struct wtbl_rx rx_wtbl; + } data = { + .g_wtbl = { + .tag = cpu_to_le16(WTBL_GENERIC), + .len = cpu_to_le16(sizeof(struct wtbl_generic)), + .muar_idx = mvif->omac_idx, + .qos = sta->wme, + .partial_aid = cpu_to_le16(sta->aid), + }, + .rx_wtbl = { + .tag = cpu_to_le16(WTBL_RX), + .len = cpu_to_le16(sizeof(struct wtbl_rx)), + .rca1 = vif->type != NL80211_IFTYPE_AP, + .rca2 = 1, + .rv = 1, + }, + }; + memcpy(data.g_wtbl.peer_addr, sta->addr, ETH_ALEN); - kfree(buf); - return ret; + return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, + WTBL_RESET_AND_SET, 2, &data, + sizeof(struct wtbl_generic) + + sizeof(struct wtbl_rx)); } int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, From 598a44344f38a5972fd4d8695939ba8570e5462a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:58 +0200 Subject: [PATCH 14/69] mt7615: mcu: unify mt7615_mcu_add_wtbl_bmc and mt7615_mcu_del_wtbl_bmc Remove duplicated code in mt7615_bss_info_changed Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 15 ++++----------- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 12 ++++++++---- .../net/wireless/mediatek/mt76/mt7615/mt7615.h | 4 ++-- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 8d7a47d1b2055..98c18c27328ee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -291,17 +291,10 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, */ if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (info->enable_beacon) { - mt7615_mcu_set_bss_info(dev, vif, 1); - mt7615_mcu_add_wtbl_bmc(dev, vif); - mt7615_mcu_set_sta_rec_bmc(dev, vif, 1); - mt7615_mcu_set_bcn(dev, vif, 1); - } else { - mt7615_mcu_set_sta_rec_bmc(dev, vif, 0); - mt7615_mcu_del_wtbl_bmc(dev, vif); - mt7615_mcu_set_bss_info(dev, vif, 0); - mt7615_mcu_set_bcn(dev, vif, 0); - } + mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); + mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); + mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); + mt7615_mcu_set_bcn(dev, vif, info->enable_beacon); } mutex_unlock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 2bda4830dbaf3..b1062c7fd5d12 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -987,10 +987,10 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, &wtbl_sec_key, buf_len); } -int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif) +static int +mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, + struct mt7615_vif *mvif) { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct { struct wtbl_generic g_wtbl; struct wtbl_rx rx_wtbl; @@ -1016,10 +1016,14 @@ int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, sizeof(struct wtbl_rx)); } -int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) +int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + if (enable) + return mt7615_mcu_add_wtbl_bmc(dev, mvif); + return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, WTBL_RESET_AND_SET, 0, NULL, 0); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 895c2904d7ebf..2331f0a9bc65f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -118,8 +118,8 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif); -int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif); +int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable); int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, From b1722925d2def3c3d6fae015ac319bcbabd8bfd2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:28:59 +0200 Subject: [PATCH 15/69] mt7615: mcu: remove unused parameter in mt7615_mcu_del_wtbl Remove unused vif parameter in mt7615_mcu_del_wtbl signature Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 98c18c27328ee..b0bb7cc123854 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -337,7 +337,7 @@ void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); mt7615_mcu_set_sta_rec(dev, vif, sta, 0); - mt7615_mcu_del_wtbl(dev, vif, sta); + mt7615_mcu_del_wtbl(dev, sta); } static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index b1062c7fd5d12..b6f16ac160417 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1060,7 +1060,7 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, sizeof(struct wtbl_rx)); } -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, +int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta) { struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 2331f0a9bc65f..81501cb64f1f4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -122,8 +122,7 @@ int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en); From 27da3bfd31577f65bfd516fe2cb06b2c0824c0b2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:00 +0200 Subject: [PATCH 16/69] mt7615: remove query from mt7615_mcu_msg_send signature Remove query parameter from mt7615_mcu_msg_send routine signature since it can be obtained from cmd value Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index b6f16ac160417..6b49db58ad0f5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -49,7 +49,7 @@ struct mt7615_fw_trailer { #define FW_START_WORKING_PDA_CR4 BIT(2) static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int query, int dest, int *wait_seq) + int cmd, int dest, int *wait_seq) { struct mt7615_mcu_txd *mcu_txd; u8 seq, q_idx, pkt_fmt; @@ -94,15 +94,14 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, mcu_txd->seq = seq; if (cmd < 0) { + mcu_txd->set_query = MCU_Q_NA; mcu_txd->cid = -cmd; } else { mcu_txd->cid = MCU_CMD_EXT_CID; + mcu_txd->set_query = MCU_Q_SET; mcu_txd->ext_cid = cmd; - if (query != MCU_Q_NA) - mcu_txd->ext_cid_ack = 1; + mcu_txd->ext_cid_ack = 1; } - - mcu_txd->set_query = query; mcu_txd->s2d_index = dest; if (wait_seq) @@ -116,9 +115,9 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, return mt76_tx_queue_skb_raw(dev, qid, skb, 0); } -static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int query, int dest, - struct sk_buff **skb_ret) +static int +mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int dest, struct sk_buff **skb_ret) { unsigned long expires = jiffies + 10 * HZ; struct mt7615_mcu_rxd *rxd; @@ -126,7 +125,7 @@ static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, mutex_lock(&dev->mt76.mmio.mcu.mutex); - ret = __mt7615_mcu_msg_send(dev, skb, cmd, query, dest, &seq); + ret = __mt7615_mcu_msg_send(dev, skb, cmd, dest, &seq); if (ret) goto out; @@ -179,7 +178,7 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, @@ -197,7 +196,7 @@ static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, return -ENOMEM; ret = __mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, - MCU_Q_NA, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); if (ret) break; @@ -221,7 +220,7 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } static int mt7615_mcu_restart(struct mt7615_dev *dev) @@ -229,7 +228,7 @@ static int mt7615_mcu_restart(struct mt7615_dev *dev) struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0); return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) @@ -249,7 +248,7 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) int ret; ret = mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL, - MCU_Q_NA, MCU_S2D_H2N, &skb_ret); + MCU_S2D_H2N, &skb_ret); if (ret) goto out; @@ -272,7 +271,7 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } static int mt7615_driver_own(struct mt7615_dev *dev) @@ -559,7 +558,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) data[off - MT_EE_NIC_CONF_0].val = eep[off]; return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_init_mac(struct mt7615_dev *dev) @@ -575,7 +574,7 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) @@ -595,7 +594,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -634,7 +633,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) @@ -665,7 +664,7 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, @@ -713,7 +712,7 @@ static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -839,7 +838,7 @@ static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, bss_info_tag_handler[i].handler(dev, bss_info, skb); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, @@ -923,7 +922,7 @@ __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, memcpy(skb_put(skb, buf_len), buf, buf_len); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } static enum mt7615_cipher_type @@ -1102,7 +1101,7 @@ __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, memcpy(skb_put(skb, buf_len), buf, buf_len); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, @@ -1231,7 +1230,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_channel(struct mt7615_dev *dev) @@ -1297,13 +1296,13 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); if (ret) return ret; skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH, - MCU_Q_SET, MCU_S2D_H2N, NULL); + MCU_S2D_H2N, NULL); } int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, From 33d9ed728eb03b02abeb69d23c1966260134bb94 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:01 +0200 Subject: [PATCH 17/69] mt7615: remove dest from mt7615_mcu_msg_send signature Remove dest parameter from mt7615_mcu_msg_send/__mt7615_mcu_msg_send routine signature since it can is always set to MCU_S2D_H2N Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 56 ++++++++----------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 6b49db58ad0f5..1fad0a7fbb4e6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -49,7 +49,7 @@ struct mt7615_fw_trailer { #define FW_START_WORKING_PDA_CR4 BIT(2) static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int dest, int *wait_seq) + int cmd, int *wait_seq) { struct mt7615_mcu_txd *mcu_txd; u8 seq, q_idx, pkt_fmt; @@ -102,7 +102,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, mcu_txd->ext_cid = cmd; mcu_txd->ext_cid_ack = 1; } - mcu_txd->s2d_index = dest; + mcu_txd->s2d_index = MCU_S2D_H2N; if (wait_seq) *wait_seq = seq; @@ -117,7 +117,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int dest, struct sk_buff **skb_ret) + int cmd, struct sk_buff **skb_ret) { unsigned long expires = jiffies + 10 * HZ; struct mt7615_mcu_rxd *rxd; @@ -125,7 +125,7 @@ mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, mutex_lock(&dev->mt76.mmio.mcu.mutex); - ret = __mt7615_mcu_msg_send(dev, skb, cmd, dest, &seq); + ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); if (ret) goto out; @@ -178,7 +178,7 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, - MCU_S2D_H2N, NULL); + NULL); } static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, @@ -196,7 +196,7 @@ static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, return -ENOMEM; ret = __mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, - MCU_S2D_H2N, NULL); + NULL); if (ret) break; @@ -219,16 +219,14 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, NULL); } static int mt7615_mcu_restart(struct mt7615_dev *dev) { struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, NULL); } static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) @@ -248,7 +246,7 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) int ret; ret = mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL, - MCU_S2D_H2N, &skb_ret); + &skb_ret); if (ret) goto out; @@ -270,8 +268,7 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ, NULL); } static int mt7615_driver_own(struct mt7615_dev *dev) @@ -558,7 +555,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) data[off - MT_EE_NIC_CONF_0].val = eep[off]; return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - MCU_S2D_H2N, NULL); + NULL); } int mt7615_mcu_init_mac(struct mt7615_dev *dev) @@ -573,8 +570,7 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL, NULL); } int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) @@ -593,8 +589,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL, NULL); } int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -632,8 +627,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, } skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE, NULL); } int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) @@ -663,8 +657,7 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL, NULL); } static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, @@ -712,7 +705,7 @@ static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE, - MCU_S2D_H2N, NULL); + NULL); } int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -838,7 +831,7 @@ static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, bss_info_tag_handler[i].handler(dev, bss_info, skb); return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE, - MCU_S2D_H2N, NULL); + NULL); } int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, @@ -921,8 +914,7 @@ __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, if (buf && buf_len) memcpy(skb_put(skb, buf_len), buf, buf_len); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE, NULL); } static enum mt7615_cipher_type @@ -1100,8 +1092,7 @@ __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, if (buf && buf_len) memcpy(skb_put(skb, buf_len), buf, buf_len); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE, NULL); } int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, @@ -1229,8 +1220,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, dev_kfree_skb(skb); skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, NULL); } int mt7615_mcu_set_channel(struct mt7615_dev *dev) @@ -1295,14 +1285,12 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) memset(req.txpower_sku, 0x3f, 49); skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, - MCU_S2D_H2N, NULL); + ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, NULL); if (ret) return ret; skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH, - MCU_S2D_H2N, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH, NULL); } int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, From 893369b769c18ad14d57f731428d97a7c04dfec6 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:02 +0200 Subject: [PATCH 18/69] mt7615: mcu: remove skb_ret from mt7615_mcu_msg_send Remove skb_ret parameter from mt7615_mcu_msg_send signature since it is actually used just by mt7615_mcu_patch_sem_ctrl. This is a prelimanry patch to use mt76 common mcu API Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 77 ++++++------------- 1 file changed, 24 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 1fad0a7fbb4e6..39fc36ad00522 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -116,8 +116,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, } static int -mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, struct sk_buff **skb_ret) +mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, int cmd) { unsigned long expires = jiffies + 10 * HZ; struct mt7615_mcu_rxd *rxd; @@ -142,18 +141,11 @@ mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, if (seq != rxd->seq) continue; - if (skb_ret) { - int hdr_len = sizeof(*rxd); - - if (!test_bit(MT76_STATE_MCU_RUNNING, - &dev->mt76.state)) - hdr_len -= 4; - skb_pull(skb, hdr_len); - *skb_ret = skb; - } else { - dev_kfree_skb(skb); + if (cmd == -MCU_CMD_PATCH_SEM_CONTROL) { + skb_pull(skb, sizeof(*rxd) - 4); + ret = *skb->data; } - + dev_kfree_skb(skb); break; } @@ -177,8 +169,7 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, - NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ); } static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, @@ -219,43 +210,26 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ); } static int mt7615_mcu_restart(struct mt7615_dev *dev) { struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ); } static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) { struct { - __le32 operation; + __le32 op; } req = { - .operation = cpu_to_le32(get ? PATCH_SEM_GET : - PATCH_SEM_RELEASE), + .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - struct event { - u8 status; - u8 reserved[3]; - } *resp; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - struct sk_buff *skb_ret; - int ret; - ret = mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL, - &skb_ret); - if (ret) - goto out; - - resp = (struct event *)(skb_ret->data); - ret = resp->status; - dev_kfree_skb(skb_ret); - -out: - return ret; + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL); } static int mt7615_mcu_start_patch(struct mt7615_dev *dev) @@ -268,7 +242,7 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ, NULL); + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ); } static int mt7615_driver_own(struct mt7615_dev *dev) @@ -554,8 +528,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) for (off = MT_EE_NIC_CONF_0; off < __MT_EE_MAX; off++) data[off - MT_EE_NIC_CONF_0].val = eep[off]; - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE); } int mt7615_mcu_init_mac(struct mt7615_dev *dev) @@ -570,7 +543,7 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL); } int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) @@ -589,7 +562,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL); } int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -627,7 +600,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, } skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE); } int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) @@ -657,7 +630,7 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) }; struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL); } static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, @@ -704,8 +677,7 @@ static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE, - NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE); } int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -830,8 +802,7 @@ static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, bss_info_tag_handler[i].handler) bss_info_tag_handler[i].handler(dev, bss_info, skb); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE, - NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE); } int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, @@ -914,7 +885,7 @@ __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, if (buf && buf_len) memcpy(skb_put(skb, buf_len), buf, buf_len); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE); } static enum mt7615_cipher_type @@ -1092,7 +1063,7 @@ __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, if (buf && buf_len) memcpy(skb_put(skb, buf_len), buf, buf_len); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE); } int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, @@ -1220,7 +1191,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, dev_kfree_skb(skb); skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD); } int mt7615_mcu_set_channel(struct mt7615_dev *dev) @@ -1285,12 +1256,12 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) memset(req.txpower_sku, 0x3f, 49); skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, NULL); + ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH); if (ret) return ret; skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH, NULL); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH); } int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, From fddc827ffc50f654d132fb85c0aee766dc147600 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:03 +0200 Subject: [PATCH 19/69] mt7615: mcu: unify __mt7615_mcu_set_dev_info and mt7615_mcu_set_dev_info Unify mt7615_mcu_set_dev_info and __mt7615_mcu_set_dev_info since the latter is run just by mt7615_mcu_set_dev_info Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 91 ++++++++----------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 4 +- 2 files changed, 38 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 39fc36ad00522..0e82fcb34e073 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -633,68 +633,49 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL); } -static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, - struct dev_info *dev_info) +int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) { - struct req_hdr { - u8 omac_idx; - u8 band_idx; - __le16 tlv_num; - u8 is_tlv_append; - u8 rsv[3]; - } __packed req_hdr = {0}; - struct req_tlv { - __le16 tag; - __le16 len; - u8 active; - u8 band_idx; - u8 omac_addr[ETH_ALEN]; - } __packed; - struct sk_buff *skb; - u16 tlv_num = 0; - - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + - sizeof(struct req_tlv)); - skb_reserve(skb, sizeof(req_hdr)); - - if (dev_info->feature & BIT(DEV_INFO_ACTIVE)) { - struct req_tlv req_tlv = { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv[3]; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 band_idx; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + }, + .tlv = { .tag = cpu_to_le16(DEV_INFO_ACTIVE), - .len = cpu_to_le16(sizeof(req_tlv)), - .active = dev_info->enable, - .band_idx = dev_info->band_idx, - }; - memcpy(req_tlv.omac_addr, dev_info->omac_addr, ETH_ALEN); - memcpy(skb_put(skb, sizeof(req_tlv)), &req_tlv, - sizeof(req_tlv)); - tlv_num++; - } - - req_hdr.omac_idx = dev_info->omac_idx; - req_hdr.band_idx = dev_info->band_idx; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - req_hdr.is_tlv_append = tlv_num ? 1 : 0; + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + .band_idx = mvif->band_idx, + }, + }; + struct sk_buff *skb; - memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + skb = mt7615_mcu_msg_alloc(&data, sizeof(data)); + if (!skb) + return -ENOMEM; return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE); } -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct dev_info dev_info = {0}; - - dev_info.omac_idx = mvif->omac_idx; - memcpy(dev_info.omac_addr, vif->addr, ETH_ALEN); - dev_info.band_idx = mvif->band_idx; - dev_info.enable = en; - dev_info.feature = BIT(DEV_INFO_ACTIVE); - - return __mt7615_mcu_set_dev_info(dev, &dev_info); -} - static void bss_info_omac_handler (struct mt7615_dev *dev, struct bss_info *bss_info, struct sk_buff *skb) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 81501cb64f1f4..e19739f9668b9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -108,8 +108,8 @@ int mt7615_eeprom_init(struct mt7615_dev *dev); int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en); +int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable); int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, int en); int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, From 1ca8089a55eeaec087d8d53452c91b1090aee4a7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 May 2019 09:54:00 +0200 Subject: [PATCH 20/69] mt7615: mcu: do not use function pointers whenever possible Remove function pointers in mt7615_mcu_set_bss_info and run function directly. Moreover remove __mt7615_mcu_set_bss_info since it is run just by mt7615_mcu_set_bss_info and remove duplicated istructions Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 220 +++++++++--------- 1 file changed, 105 insertions(+), 115 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 0e82fcb34e073..2ef4e4ef3a787 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -676,154 +676,107 @@ int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE); } -static void bss_info_omac_handler (struct mt7615_dev *dev, - struct bss_info *bss_info, - struct sk_buff *skb) +static void +mt7615_mcu_bss_info_omac_header(struct mt7615_vif *mvif, u8 *data, + u32 conn_type) { - struct bss_info_omac tlv = {0}; - - tlv.tag = cpu_to_le16(BSS_INFO_OMAC); - tlv.len = cpu_to_le16(sizeof(tlv)); - tlv.hw_bss_idx = (bss_info->omac_idx > EXT_BSSID_START) ? - HW_BSSID_0 : bss_info->omac_idx; - tlv.omac_idx = bss_info->omac_idx; - tlv.band_idx = bss_info->band_idx; - tlv.conn_type = cpu_to_le32(bss_info->conn_type); - - memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); + struct bss_info_omac *hdr = (struct bss_info_omac *)data; + u8 idx; + + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + hdr->tag = cpu_to_le16(BSS_INFO_OMAC); + hdr->len = cpu_to_le16(sizeof(struct bss_info_omac)); + hdr->hw_bss_idx = idx; + hdr->omac_idx = mvif->omac_idx; + hdr->band_idx = mvif->band_idx; + hdr->conn_type = cpu_to_le32(conn_type); } -static void bss_info_basic_handler (struct mt7615_dev *dev, - struct bss_info *bss_info, - struct sk_buff *skb) +static void +mt7615_mcu_bss_info_basic_header(struct ieee80211_vif *vif, u8 *data, + u32 net_type, u8 tx_wlan_idx, + bool enable) { - struct bss_info_basic tlv = {0}; - - tlv.tag = cpu_to_le16(BSS_INFO_BASIC); - tlv.len = cpu_to_le16(sizeof(tlv)); - tlv.network_type = cpu_to_le32(bss_info->network_type); - tlv.active = bss_info->enable; - tlv.bcn_interval = cpu_to_le16(bss_info->bcn_interval); - memcpy(tlv.bssid, bss_info->bssid, ETH_ALEN); - tlv.wmm_idx = bss_info->wmm_idx; - tlv.dtim_period = bss_info->dtim_period; - tlv.bmc_tx_wlan_idx = bss_info->bmc_tx_wlan_idx; - - memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info_basic *hdr = (struct bss_info_basic *)data; + + hdr->tag = cpu_to_le16(BSS_INFO_BASIC); + hdr->len = cpu_to_le16(sizeof(struct bss_info_basic)); + hdr->network_type = cpu_to_le32(net_type); + hdr->active = enable; + hdr->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + memcpy(hdr->bssid, vif->bss_conf.bssid, ETH_ALEN); + hdr->wmm_idx = mvif->wmm_idx; + hdr->dtim_period = vif->bss_conf.dtim_period; + hdr->bmc_tx_wlan_idx = tx_wlan_idx; } -static void bss_info_ext_bss_handler (struct mt7615_dev *dev, - struct bss_info *bss_info, - struct sk_buff *skb) +static void +mt7615_mcu_bss_info_ext_header(struct mt7615_vif *mvif, u8 *data) { /* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ #define BCN_TX_ESTIMATE_TIME (4096 + 20) - struct bss_info_ext_bss tlv = {0}; + struct bss_info_ext_bss *hdr = (struct bss_info_ext_bss *)data; int ext_bss_idx; - ext_bss_idx = bss_info->omac_idx - EXT_BSSID_START; - + ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; if (ext_bss_idx < 0) return; - tlv.tag = cpu_to_le16(BSS_INFO_EXT_BSS); - tlv.len = cpu_to_le16(sizeof(tlv)); - tlv.mbss_tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - - memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); + hdr->tag = cpu_to_le16(BSS_INFO_EXT_BSS); + hdr->len = cpu_to_le16(sizeof(struct bss_info_ext_bss)); + hdr->mbss_tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; } -static struct bss_info_tag_handler bss_info_tag_handler[] = { - {BSS_INFO_OMAC, sizeof(struct bss_info_omac), bss_info_omac_handler}, - {BSS_INFO_BASIC, sizeof(struct bss_info_basic), bss_info_basic_handler}, - {BSS_INFO_RF_CH, sizeof(struct bss_info_rf_ch), NULL}, - {BSS_INFO_PM, 0, NULL}, - {BSS_INFO_UAPSD, 0, NULL}, - {BSS_INFO_ROAM_DETECTION, 0, NULL}, - {BSS_INFO_LQ_RM, 0, NULL}, - {BSS_INFO_EXT_BSS, sizeof(struct bss_info_ext_bss), bss_info_ext_bss_handler}, - {BSS_INFO_BMC_INFO, 0, NULL}, - {BSS_INFO_SYNC_MODE, 0, NULL}, - {BSS_INFO_RA, 0, NULL}, - {BSS_INFO_MAX_NUM, 0, NULL}, -}; - -static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, - struct bss_info *bss_info) +int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, int en) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct req_hdr { u8 bss_idx; u8 rsv0; __le16 tlv_num; u8 is_tlv_append; u8 rsv1[3]; - } __packed req_hdr = {0}; + } __packed; + int len = sizeof(struct req_hdr) + sizeof(struct bss_info_basic); + int ret, i, features = BIT(BSS_INFO_BASIC), ntlv = 1; + u32 conn_type = 0, net_type = NETWORK_INFRA; + u8 *buf, *data, tx_wlan_idx = 0; + struct req_hdr *hdr; struct sk_buff *skb; - u16 tlv_num = 0; - u32 size = 0; - int i; - for (i = 0; i < BSS_INFO_MAX_NUM; i++) - if ((BIT(bss_info_tag_handler[i].tag) & bss_info->feature) && - bss_info_tag_handler[i].handler) { - tlv_num++; - size += bss_info_tag_handler[i].len; + if (en) { + len += sizeof(struct bss_info_omac); + features |= BIT(BSS_INFO_OMAC); + if (mvif->omac_idx > EXT_BSSID_START) { + len += sizeof(struct bss_info_ext_bss); + features |= BIT(BSS_INFO_EXT_BSS); + ntlv++; } - - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + size); - - req_hdr.bss_idx = bss_info->bss_idx; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - req_hdr.is_tlv_append = tlv_num ? 1 : 0; - - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - for (i = 0; i < BSS_INFO_MAX_NUM; i++) - if ((BIT(bss_info_tag_handler[i].tag) & bss_info->feature) && - bss_info_tag_handler[i].handler) - bss_info_tag_handler[i].handler(dev, bss_info, skb); - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE); -} - -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, int en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct bss_info bss_info = { - .bss_idx = mvif->idx, - .omac_idx = mvif->omac_idx, - .band_idx = mvif->band_idx, - .bcn_interval = vif->bss_conf.beacon_int, - .dtim_period = vif->bss_conf.dtim_period, - .enable = en, - .feature = BIT(BSS_INFO_BASIC), - .wmm_idx = mvif->wmm_idx, - }; + ntlv++; + } switch (vif->type) { case NL80211_IFTYPE_AP: - bss_info.bmc_tx_wlan_idx = mvif->sta.wcid.idx; - bss_info.network_type = NETWORK_INFRA; - bss_info.conn_type = CONNECTION_INFRA_AP; + tx_wlan_idx = mvif->sta.wcid.idx; + conn_type = CONNECTION_INFRA_AP; break; case NL80211_IFTYPE_STATION: { - /* find the unicast entry for sta mode bmc tx */ - struct ieee80211_sta *ap_sta; + struct ieee80211_sta *sta; struct mt7615_sta *msta; rcu_read_lock(); - ap_sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!ap_sta) { + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { rcu_read_unlock(); return -EINVAL; } - msta = (struct mt7615_sta *)ap_sta->drv_priv; - bss_info.bmc_tx_wlan_idx = msta->wcid.idx; - bss_info.network_type = NETWORK_INFRA; - bss_info.conn_type = CONNECTION_INFRA_STA; + msta = (struct mt7615_sta *)sta->drv_priv; + tx_wlan_idx = msta->wcid.idx; + conn_type = CONNECTION_INFRA_STA; rcu_read_unlock(); break; @@ -832,15 +785,52 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, WARN_ON(1); break; } - memcpy(bss_info.bssid, vif->bss_conf.bssid, ETH_ALEN); - if (en) { - bss_info.feature |= BIT(BSS_INFO_OMAC); - if (mvif->omac_idx > EXT_BSSID_START) - bss_info.feature |= BIT(BSS_INFO_EXT_BSS); + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + hdr = (struct req_hdr *)buf; + hdr->bss_idx = mvif->idx; + hdr->tlv_num = cpu_to_le16(ntlv); + hdr->is_tlv_append = 1; + + data = buf + sizeof(*hdr); + for (i = 0; i < BSS_INFO_MAX_NUM; i++) { + int tag = ffs(features & BIT(i)) - 1; + + switch (tag) { + case BSS_INFO_OMAC: + mt7615_mcu_bss_info_omac_header(mvif, data, + conn_type); + data += sizeof(struct bss_info_omac); + break; + case BSS_INFO_BASIC: + mt7615_mcu_bss_info_basic_header(vif, data, net_type, + tx_wlan_idx, en); + data += sizeof(struct bss_info_basic); + break; + case BSS_INFO_EXT_BSS: + mt7615_mcu_bss_info_ext_header(mvif, data); + data += sizeof(struct bss_info_ext_bss); + break; + default: + break; + } + } + + skb = mt7615_mcu_msg_alloc(buf, len); + if (!skb) { + ret = -ENOMEM; + goto out; } - return __mt7615_mcu_set_bss_info(dev, &bss_info); + ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE); + +out: + kfree(buf); + + return ret; } static int From eb2024b08731f0d7e14206566dc30d4e57f361fc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:05 +0200 Subject: [PATCH 21/69] mt7615: mcu: remove unused structure in mcu.h Remove following struct no longer used: - dev_info - bss_info - bss_info_tag_handler Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.h | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 9455f8fa475d0..2d3f88ed8dc92 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -131,41 +131,11 @@ enum { #define CONN_STATE_CONNECT 1 #define CONN_STATE_PORT_SECURE 2 -struct dev_info { - u8 omac_idx; - u8 omac_addr[ETH_ALEN]; - u8 band_idx; - u8 enable; - u32 feature; -}; - enum { DEV_INFO_ACTIVE, DEV_INFO_MAX_NUM }; -struct bss_info { - u8 bss_idx; - u8 bssid[ETH_ALEN]; - u8 omac_idx; - u8 band_idx; - u8 bmc_tx_wlan_idx; /* for bmc tx (sta mode use uc entry) */ - u8 wmm_idx; - u32 network_type; - u32 conn_type; - u16 bcn_interval; - u8 dtim_period; - u8 enable; - u32 feature; -}; - -struct bss_info_tag_handler { - u32 tag; - u32 len; - void (*handler)(struct mt7615_dev *dev, - struct bss_info *bss_info, struct sk_buff *skb); -}; - struct bss_info_omac { __le16 tag; __le16 len; From 516c3e3805339fb189e4842df9081a85644ac1b8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:06 +0200 Subject: [PATCH 22/69] mt7615: mcu: use standard signature for mt7615_mcu_msg_send Use mt76 common signature for mt7615_mcu_msg_send. Move skb allocation in mt7615_mcu_msg_send and remove duplicated code. Remove __mt7615_mcu_set_wtbl and __mt7615_mcu_set_sta_rec since now are used just to send mcu msgs. This is a preliminary patch for mt7615-mt7603 mcu code unification Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 614 +++++++++--------- .../net/wireless/mediatek/mt76/mt7615/mcu.h | 19 +- 2 files changed, 337 insertions(+), 296 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 2ef4e4ef3a787..474473b6d5261 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -57,9 +57,6 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, u32 val; __le32 *txd; - if (!skb) - return -EINVAL; - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; if (!seq) seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; @@ -116,19 +113,25 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, } static int -mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, int cmd) +mt7615_mcu_msg_send(struct mt7615_dev *dev, int cmd, const void *data, + int len, bool wait_resp) { unsigned long expires = jiffies + 10 * HZ; struct mt7615_mcu_rxd *rxd; + struct sk_buff *skb; int ret, seq; + skb = mt7615_mcu_msg_alloc(data, len); + if (!skb) + return -ENOMEM; + mutex_lock(&dev->mt76.mmio.mcu.mutex); ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); if (ret) goto out; - while (1) { + while (wait_resp) { skb = mt76_mcu_get_response(&dev->mt76, expires); if (!skb) { dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", @@ -167,9 +170,9 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, .len = cpu_to_le32(len), .mode = cpu_to_le32(mode), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ); + return mt7615_mcu_msg_send(dev, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); } static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, @@ -208,16 +211,15 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, .option = cpu_to_le32(option), .addr = cpu_to_le32(addr), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ); + return mt7615_mcu_msg_send(dev, -MCU_CMD_FW_START_REQ, + &req, sizeof(req), true); } static int mt7615_mcu_restart(struct mt7615_dev *dev) { - struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0); - - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ); + return mt7615_mcu_msg_send(dev, -MCU_CMD_RESTART_DL_REQ, + NULL, 0, true); } static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) @@ -227,9 +229,9 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) } req = { .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL); + return mt7615_mcu_msg_send(dev, -MCU_CMD_PATCH_SEM_CONTROL, + &req, sizeof(req), true); } static int mt7615_mcu_start_patch(struct mt7615_dev *dev) @@ -240,9 +242,9 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) } req = { .check_crc = 0, }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ); + return mt7615_mcu_msg_send(dev, -MCU_CMD_PATCH_FINISH_REQ, + &req, sizeof(req), true); } static int mt7615_driver_own(struct mt7615_dev *dev) @@ -502,9 +504,6 @@ void mt7615_mcu_exit(struct mt7615_dev *dev) int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) { - struct req_data { - u8 val; - } __packed; struct { u8 buffer_mode; u8 pad; @@ -513,22 +512,22 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) .buffer_mode = 1, .len = __MT_EE_MAX - MT_EE_NIC_CONF_0, }; - struct sk_buff *skb; - struct req_data *data; - const int size = (__MT_EE_MAX - MT_EE_NIC_CONF_0) * - sizeof(struct req_data); - u8 *eep = (u8 *)dev->mt76.eeprom.data; - u16 off; + int ret, len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + + req = kzalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; - skb = mt7615_mcu_msg_alloc(NULL, size + sizeof(req_hdr)); - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - data = (struct req_data *)skb_put(skb, size); - memset(data, 0, size); + memcpy(req, &req_hdr, sizeof(req_hdr)); + memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, + __MT_EE_MAX - MT_EE_NIC_CONF_0); - for (off = MT_EE_NIC_CONF_0; off < __MT_EE_MAX; off++) - data[off - MT_EE_NIC_CONF_0].val = eep[off]; + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + req, len, true); + kfree(req); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE); + return ret; } int mt7615_mcu_init_mac(struct mt7615_dev *dev) @@ -541,9 +540,9 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) .enable = 1, .band = 0, }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_MAC_INIT_CTRL, + &req, sizeof(req), true); } int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) @@ -560,9 +559,9 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) .len_thresh = cpu_to_le32(val), .pkt_thresh = cpu_to_le32(0x2), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_PROTECT_CTRL, + &req, sizeof(req), true); } int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -588,7 +587,6 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, .aifs = params->aifs, .txop = cpu_to_le16(params->txop), }; - struct sk_buff *skb; if (params->cw_min) { req.valid |= WMM_CW_MIN_SET; @@ -599,8 +597,8 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, req.cw_max = cpu_to_le16(params->cw_max); } - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_EDCA_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) @@ -628,9 +626,9 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, .band_idx = 0, }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_PM_STATE_CTRL, + &req, sizeof(req), true); } int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, @@ -666,14 +664,10 @@ int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, .band_idx = mvif->band_idx, }, }; - struct sk_buff *skb; memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); - skb = mt7615_mcu_msg_alloc(&data, sizeof(data)); - if (!skb) - return -ENOMEM; - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); } static void @@ -744,7 +738,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, u32 conn_type = 0, net_type = NETWORK_INFRA; u8 *buf, *data, tx_wlan_idx = 0; struct req_hdr *hdr; - struct sk_buff *skb; if (en) { len += sizeof(struct bss_info_omac); @@ -819,46 +812,13 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, } } - skb = mt7615_mcu_msg_alloc(buf, len); - if (!skb) { - ret = -ENOMEM; - goto out; - } - - ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE); - -out: + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_BSS_INFO_UPDATE, + buf, len, true); kfree(buf); return ret; } -static int -__mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, - int operation, int ntlv, void *buf, - int buf_len) -{ - struct req_hdr { - u8 wlan_idx; - u8 operation; - __le16 tlv_num; - u8 rsv[4]; - } __packed req_hdr = { - .wlan_idx = wlan_idx, - .operation = operation, - .tlv_num = cpu_to_le16(ntlv), - }; - struct sk_buff *skb; - - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - if (buf && buf_len) - memcpy(skb_put(skb, buf_len), buf, buf_len); - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE); -} - static enum mt7615_cipher_type mt7615_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) { @@ -896,28 +856,38 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd) { - struct wtbl_sec_key wtbl_sec_key = {0}; - int buf_len = sizeof(struct wtbl_sec_key); - u8 cipher; - - wtbl_sec_key.tag = cpu_to_le16(WTBL_SEC_KEY); - wtbl_sec_key.len = cpu_to_le16(buf_len); - wtbl_sec_key.add = cmd; + struct { + struct wtbl_req_hdr hdr; + struct wtbl_sec_key key; + } req = { + .hdr = { + .wlan_idx = wcid, + .operation = WTBL_SET, + .tlv_num = cpu_to_le16(1), + }, + .key = { + .tag = cpu_to_le16(WTBL_SEC_KEY), + .len = cpu_to_le16(sizeof(struct wtbl_sec_key)), + .add = cmd, + }, + }; if (cmd == SET_KEY) { - cipher = mt7615_get_key_info(key, wtbl_sec_key.key_material); + u8 cipher; + + cipher = mt7615_get_key_info(key, req.key.key_material); if (cipher == MT_CIPHER_NONE && key) return -EOPNOTSUPP; - wtbl_sec_key.cipher_id = cipher; - wtbl_sec_key.key_id = key->keyidx; - wtbl_sec_key.key_len = key->keylen; + req.key.cipher_id = cipher; + req.key.key_id = key->keyidx; + req.key.key_len = key->keylen; } else { - wtbl_sec_key.key_len = sizeof(wtbl_sec_key.key_material); + req.key.key_len = sizeof(req.key.key_material); } - return __mt7615_mcu_set_wtbl(dev, wcid, WTBL_SET, 1, - &wtbl_sec_key, buf_len); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } static int @@ -925,9 +895,15 @@ mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct mt7615_vif *mvif) { struct { + struct wtbl_req_hdr hdr; struct wtbl_generic g_wtbl; struct wtbl_rx rx_wtbl; - } data = { + } req = { + .hdr = { + .wlan_idx = mvif->sta.wcid.idx, + .operation = WTBL_RESET_AND_SET, + .tlv_num = cpu_to_le16(2), + }, .g_wtbl = { .tag = cpu_to_le16(WTBL_GENERIC), .len = cpu_to_le16(sizeof(struct wtbl_generic)), @@ -941,12 +917,10 @@ mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, .rv = 1, }, }; - eth_broadcast_addr(data.g_wtbl.peer_addr); + eth_broadcast_addr(req.g_wtbl.peer_addr); - return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, 2, &data, - sizeof(struct wtbl_generic) + - sizeof(struct wtbl_rx)); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, @@ -954,11 +928,17 @@ int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - if (enable) - return mt7615_mcu_add_wtbl_bmc(dev, mvif); + if (!enable) { + struct wtbl_req_hdr req = { + .wlan_idx = mvif->sta.wcid.idx, + .operation = WTBL_RESET_AND_SET, + }; - return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, 0, NULL, 0); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); + } + + return mt7615_mcu_add_wtbl_bmc(dev, mvif); } int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -967,9 +947,15 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; struct { + struct wtbl_req_hdr hdr; struct wtbl_generic g_wtbl; struct wtbl_rx rx_wtbl; - } data = { + } req = { + .hdr = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_RESET_AND_SET, + .tlv_num = cpu_to_le16(2), + }, .g_wtbl = { .tag = cpu_to_le16(WTBL_GENERIC), .len = cpu_to_le16(sizeof(struct wtbl_generic)), @@ -985,81 +971,69 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, .rv = 1, }, }; - memcpy(data.g_wtbl.peer_addr, sta->addr, ETH_ALEN); + memcpy(req.g_wtbl.peer_addr, sta->addr, ETH_ALEN); - return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, - WTBL_RESET_AND_SET, 2, &data, - sizeof(struct wtbl_generic) + - sizeof(struct wtbl_rx)); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta) { struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct wtbl_req_hdr req = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_RESET_AND_SET, + }; - return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, - WTBL_RESET_AND_SET, 0, NULL, 0); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) { - return __mt7615_mcu_set_wtbl(dev, 0, WTBL_RESET_ALL, 0, NULL, 0); -} - -static int -__mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, - int wlan_idx, int muar_idx, int ntlv, - void *buf, int buf_len) -{ - struct req_hdr { - u8 bss_idx; - u8 wlan_idx; - __le16 tlv_num; - u8 is_tlv_append; - u8 muar_idx; - u8 rsv[2]; - } __packed req_hdr = { - .bss_idx = bss_idx, - .wlan_idx = wlan_idx, - .tlv_num = cpu_to_le16(ntlv), - .is_tlv_append = !!ntlv, - .muar_idx = muar_idx, + struct wtbl_req_hdr req = { + .operation = WTBL_RESET_ALL, }; - struct sk_buff *skb; - - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - if (buf && buf_len) - memcpy(skb_put(skb, buf_len), buf, buf_len); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct sta_rec_basic sta_rec_basic = {0}; - int buf_len = sizeof(struct sta_rec_basic); + struct { + struct sta_req_hdr hdr; + struct sta_rec_basic basic; + } req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = mvif->sta.wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .basic = { + .tag = cpu_to_le16(STA_REC_BASIC), + .len = cpu_to_le16(sizeof(struct sta_rec_basic)), + .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), + }, + }; + eth_broadcast_addr(req.basic.peer_addr); - sta_rec_basic.tag = cpu_to_le16(STA_REC_BASIC); - sta_rec_basic.len = cpu_to_le16(buf_len); - sta_rec_basic.conn_type = cpu_to_le32(CONNECTION_INFRA_BC); - eth_broadcast_addr(sta_rec_basic.peer_addr); if (en) { - sta_rec_basic.conn_state = CONN_STATE_PORT_SECURE; - sta_rec_basic.extra_info = - cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + req.basic.conn_state = CONN_STATE_PORT_SECURE; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | + EXTRA_INFO_NEW); } else { - sta_rec_basic.conn_state = CONN_STATE_DISCONNECT; - sta_rec_basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + req.basic.conn_state = CONN_STATE_DISCONNECT; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return __mt7615_mcu_set_sta_rec(dev, mvif->idx, mvif->sta.wcid.idx, - mvif->omac_idx, 1, &sta_rec_basic, - buf_len); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + &req, sizeof(req), true); } static void sta_rec_convert_vif_type(enum nl80211_iftype type, u32 *conn_type) @@ -1084,36 +1058,49 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct sta_rec_basic sta_rec_basic = {0}; - int buf_len = sizeof(struct sta_rec_basic); u32 conn_type = 0; - sta_rec_convert_vif_type(vif->type, &conn_type); + struct { + struct sta_req_hdr hdr; + struct sta_rec_basic basic; + } req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta->wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .basic = { + .tag = cpu_to_le16(STA_REC_BASIC), + .len = cpu_to_le16(sizeof(struct sta_rec_basic)), + .qos = sta->wme, + .aid = cpu_to_le16(sta->aid), + }, + }; + memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); - sta_rec_basic.tag = cpu_to_le16(STA_REC_BASIC); - sta_rec_basic.len = cpu_to_le16(buf_len); - sta_rec_basic.conn_type = cpu_to_le32(conn_type); - sta_rec_basic.qos = sta->wme; - sta_rec_basic.aid = cpu_to_le16(sta->aid); - memcpy(sta_rec_basic.peer_addr, sta->addr, ETH_ALEN); + sta_rec_convert_vif_type(vif->type, &conn_type); + req.basic.conn_type = cpu_to_le32(conn_type); if (en) { - sta_rec_basic.conn_state = CONN_STATE_PORT_SECURE; - sta_rec_basic.extra_info = - cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + req.basic.conn_state = CONN_STATE_PORT_SECURE; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | + EXTRA_INFO_NEW); } else { - sta_rec_basic.conn_state = CONN_STATE_DISCONNECT; - sta_rec_basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + req.basic.conn_state = CONN_STATE_DISCONNECT; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, 1, &sta_rec_basic, - buf_len); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, int en) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct req { u8 omac_idx; u8 enable; @@ -1129,14 +1116,18 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, /* bss color change */ u8 bcc_cnt; __le16 bcc_ie_pos; - } __packed req = {0}; - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - struct sk_buff *skb; + } __packed req = { + .omac_idx = mvif->omac_idx, + .enable = en, + .wlan_idx = wcid->idx, + .band_idx = mvif->band_idx, + /* pky_type: 0 for bcn, 1 for tim */ + .pkt_type = 0, + }; u16 tim_off, tim_len; + struct sk_buff *skb; skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, &tim_len); - if (!skb) return -EINVAL; @@ -1149,20 +1140,13 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, 0, NULL); memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); - - req.omac_idx = mvif->omac_idx; - req.enable = en; - req.wlan_idx = wcid->idx; - req.band_idx = mvif->band_idx; - /* pky_type: 0 for bcn, 1 for tim */ - req.pkt_type = 0; req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + tim_off); dev_kfree_skb(skb); - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_BCN_OFFLOAD, + &req, sizeof(req), true); } int mt7615_mcu_set_channel(struct mt7615_dev *dev) @@ -1187,7 +1171,6 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) u8 txpower_sku[53]; u8 rsv2[3]; } req = {0}; - struct sk_buff *skb; int ret; req.control_chan = chdef->chan->hw_value; @@ -1223,16 +1206,15 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) default: req.bw = CMD_CBW_20MHZ; } - memset(req.txpower_sku, 0x3f, 49); - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH); + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_CHANNEL_SWITCH, + &req, sizeof(req), true); if (ret) return ret; - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_SET_RX_PATH, + &req, sizeof(req), true); } int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -1240,9 +1222,11 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, { struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_ht *wtbl_ht; + struct wtbl_req_hdr *wtbl_hdr; + struct sta_req_hdr *sta_hdr; struct wtbl_raw *wtbl_raw; - struct sta_rec_ht *sta_rec_ht; + struct sta_rec_ht *sta_ht; + struct wtbl_ht *wtbl_ht; int buf_len, ret, ntlv = 2; u32 msk, val = 0; u8 *buf; @@ -1251,15 +1235,20 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, if (!buf) return -ENOMEM; + wtbl_hdr = (struct wtbl_req_hdr *)buf; + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_SET; + buf_len = sizeof(*wtbl_hdr); + /* ht basic */ - buf_len = sizeof(*wtbl_ht); - wtbl_ht = (struct wtbl_ht *)buf; + wtbl_ht = (struct wtbl_ht *)(buf + buf_len); wtbl_ht->tag = cpu_to_le16(WTBL_HT); wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); wtbl_ht->ht = 1; wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; wtbl_ht->af = sta->ht_cap.ampdu_factor; wtbl_ht->mm = sta->ht_cap.ampdu_density; + buf_len += sizeof(*wtbl_ht); if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) val |= MT_WTBL_W5_SHORT_GI_20; @@ -1309,41 +1298,48 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_raw->msk = cpu_to_le32(~msk); wtbl_raw->val = cpu_to_le32(val); - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, ntlv, - buf, buf_len); - if (ret) { - kfree(buf); - return ret; - } + wtbl_hdr->tlv_num = cpu_to_le16(ntlv); + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + buf, buf_len, true); + if (ret) + goto out; memset(buf, 0, MT7615_WTBL_UPDATE_MAX_SIZE); - buf_len = sizeof(*sta_rec_ht); - sta_rec_ht = (struct sta_rec_ht *)buf; - sta_rec_ht->tag = cpu_to_le16(STA_REC_HT); - sta_rec_ht->len = cpu_to_le16(sizeof(*sta_rec_ht)); - sta_rec_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); - ntlv = 1; + sta_hdr = (struct sta_req_hdr *)buf; + sta_hdr->bss_idx = mvif->idx; + sta_hdr->wlan_idx = msta->wcid.idx; + sta_hdr->is_tlv_append = 1; + ntlv = sta->vht_cap.vht_supported ? 2 : 1; + sta_hdr->tlv_num = cpu_to_le16(ntlv); + sta_hdr->muar_idx = mvif->omac_idx; + buf_len = sizeof(*sta_hdr); + + sta_ht = (struct sta_rec_ht *)(buf + buf_len); + sta_ht->tag = cpu_to_le16(STA_REC_HT); + sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); + sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + buf_len += sizeof(*sta_ht); if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_rec_vht; - - sta_rec_vht = (struct sta_rec_vht *)(buf + buf_len); - buf_len += sizeof(*sta_rec_vht); - sta_rec_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_rec_vht->len = cpu_to_le16(sizeof(*sta_rec_vht)); - sta_rec_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_rec_vht->vht_rx_mcs_map = + struct sta_rec_vht *sta_vht; + + sta_vht = (struct sta_rec_vht *)(buf + buf_len); + buf_len += sizeof(*sta_vht); + sta_vht->tag = cpu_to_le16(STA_REC_VHT); + sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); + sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + sta_vht->vht_rx_mcs_map = cpu_to_le16(sta->vht_cap.vht_mcs.rx_mcs_map); - sta_rec_vht->vht_tx_mcs_map = + sta_vht->vht_tx_mcs_map = cpu_to_le16(sta->vht_cap.vht_mcs.tx_mcs_map); - ntlv++; } - ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, ntlv, buf, - buf_len); + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + buf, buf_len, true); +out: kfree(buf); + return ret; } @@ -1351,100 +1347,128 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add) { - struct ieee80211_sta *sta = params->sta; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - u8 ba_range[8] = {4, 8, 12, 24, 36, 48, 54, 64}; - u16 tid = params->tid; - u16 ba_size = params->buf_size; - u16 ssn = params->ssn; - struct wtbl_ba wtbl_ba = {0}; - struct sta_rec_ba sta_rec_ba = {0}; - int ret, buf_len; - - buf_len = sizeof(struct wtbl_ba); - - wtbl_ba.tag = cpu_to_le16(WTBL_BA); - wtbl_ba.len = cpu_to_le16(buf_len); - wtbl_ba.tid = tid; - wtbl_ba.ba_type = MT_BA_TYPE_ORIGINATOR; + struct { + struct wtbl_req_hdr hdr; + struct wtbl_ba ba; + } wtbl_req = { + .hdr = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_SET, + .tlv_num = cpu_to_le16(1), + }, + .ba = { + .tag = cpu_to_le16(WTBL_BA), + .len = cpu_to_le16(sizeof(struct wtbl_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_ORIGINATOR, + .sn = add ? cpu_to_le16(params->ssn) : 0, + .ba_en = add, + }, + }; + struct { + struct sta_req_hdr hdr; + struct sta_rec_ba ba; + } sta_req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta->wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .ba = { + .tag = cpu_to_le16(STA_REC_BA), + .len = cpu_to_le16(sizeof(struct sta_rec_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_ORIGINATOR, + .amsdu = params->amsdu, + .ba_en = add << params->tid, + .ssn = cpu_to_le16(params->ssn), + .winsize = cpu_to_le16(params->buf_size), + }, + }; + int ret; if (add) { - u8 idx; + u8 idx, ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; for (idx = 7; idx > 0; idx--) { - if (ba_size >= ba_range[idx]) + if (params->buf_size >= ba_range[idx]) break; } - wtbl_ba.sn = cpu_to_le16(ssn); - wtbl_ba.ba_en = 1; - wtbl_ba.ba_winsize_idx = idx; + wtbl_req.ba.ba_winsize_idx = idx; } - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, 1, - &wtbl_ba, buf_len); + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &wtbl_req, sizeof(wtbl_req), true); if (ret) return ret; - buf_len = sizeof(struct sta_rec_ba); - - sta_rec_ba.tag = cpu_to_le16(STA_REC_BA); - sta_rec_ba.len = cpu_to_le16(buf_len); - sta_rec_ba.tid = tid; - sta_rec_ba.ba_type = MT_BA_TYPE_ORIGINATOR; - sta_rec_ba.amsdu = params->amsdu; - sta_rec_ba.ba_en = add << tid; - sta_rec_ba.ssn = cpu_to_le16(ssn); - sta_rec_ba.winsize = cpu_to_le16(ba_size); - - return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, 1, &sta_rec_ba, - buf_len); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + &sta_req, sizeof(sta_req), true); } int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add) { - struct ieee80211_sta *sta = params->sta; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - u16 tid = params->tid; - struct wtbl_ba wtbl_ba = {0}; - struct sta_rec_ba sta_rec_ba = {0}; - int ret, buf_len; - - buf_len = sizeof(struct sta_rec_ba); - - sta_rec_ba.tag = cpu_to_le16(STA_REC_BA); - sta_rec_ba.len = cpu_to_le16(buf_len); - sta_rec_ba.tid = tid; - sta_rec_ba.ba_type = MT_BA_TYPE_RECIPIENT; - sta_rec_ba.amsdu = params->amsdu; - sta_rec_ba.ba_en = add << tid; - sta_rec_ba.ssn = cpu_to_le16(params->ssn); - sta_rec_ba.winsize = cpu_to_le16(params->buf_size); - - ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, 1, &sta_rec_ba, - buf_len); - if (ret || !add) - return ret; + struct { + struct wtbl_req_hdr hdr; + struct wtbl_ba ba; + } wtbl_req = { + .hdr = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_SET, + .tlv_num = cpu_to_le16(1), + }, + .ba = { + .tag = cpu_to_le16(WTBL_BA), + .len = cpu_to_le16(sizeof(struct wtbl_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_RECIPIENT, + .rst_ba_tid = params->tid, + .rst_ba_sel = RST_BA_MAC_TID_MATCH, + .rst_ba_sb = 1, + }, + }; + struct { + struct sta_req_hdr hdr; + struct sta_rec_ba ba; + } sta_req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta->wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .ba = { + .tag = cpu_to_le16(STA_REC_BA), + .len = cpu_to_le16(sizeof(struct sta_rec_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_RECIPIENT, + .amsdu = params->amsdu, + .ba_en = add << params->tid, + .ssn = cpu_to_le16(params->ssn), + .winsize = cpu_to_le16(params->buf_size), + }, + }; + int ret; - buf_len = sizeof(struct wtbl_ba); + memcpy(wtbl_req.ba.peer_addr, params->sta->addr, ETH_ALEN); - wtbl_ba.tag = cpu_to_le16(WTBL_BA); - wtbl_ba.len = cpu_to_le16(buf_len); - wtbl_ba.tid = tid; - wtbl_ba.ba_type = MT_BA_TYPE_RECIPIENT; - memcpy(wtbl_ba.peer_addr, sta->addr, ETH_ALEN); - wtbl_ba.rst_ba_tid = tid; - wtbl_ba.rst_ba_sel = RST_BA_MAC_TID_MATCH; - wtbl_ba.rst_ba_sb = 1; + ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + &sta_req, sizeof(sta_req), true); + if (ret || !add) + return ret; - return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, - 1, &wtbl_ba, buf_len); + return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + &wtbl_req, sizeof(wtbl_req), true); } void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 2d3f88ed8dc92..e96efb13fa4d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -201,6 +201,13 @@ enum { WTBL_RESET_ALL }; +struct wtbl_req_hdr { + u8 wlan_idx; + u8 operation; + __le16 tlv_num; + u8 rsv[4]; +} __packed; + struct wtbl_generic { __le16 tag; __le16 len; @@ -366,7 +373,8 @@ struct wtbl_raw { __le32 val; } __packed; -#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_generic) + \ +#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) + \ @@ -400,6 +408,15 @@ enum { WTBL_MAX_NUM }; +struct sta_req_hdr { + u8 bss_idx; + u8 wlan_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 muar_idx; + u8 rsv[2]; +} __packed; + struct sta_rec_basic { __le16 tag; __le16 len; From a3a2c2e79c13e6cc70934a6c88f954a9955b5ac0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:07 +0200 Subject: [PATCH 23/69] mt7615: initialize mt76_mcu_ops data structure Use __mt76_mcu_send_msg wrapper instead of mt7615_mcu_msg_send. This is a preliminary patch for mt7615-mt7603 mcu code unification Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 474473b6d5261..c3df9de93c8fe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -113,9 +113,10 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, } static int -mt7615_mcu_msg_send(struct mt7615_dev *dev, int cmd, const void *data, +mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp) { + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); unsigned long expires = jiffies + 10 * HZ; struct mt7615_mcu_rxd *rxd; struct sk_buff *skb; @@ -125,16 +126,16 @@ mt7615_mcu_msg_send(struct mt7615_dev *dev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&dev->mt76.mmio.mcu.mutex); + mutex_lock(&mdev->mmio.mcu.mutex); ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); if (ret) goto out; while (wait_resp) { - skb = mt76_mcu_get_response(&dev->mt76, expires); + skb = mt76_mcu_get_response(mdev, expires); if (!skb) { - dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", + dev_err(mdev->dev, "Message %d (seq %d) timeout\n", cmd, seq); ret = -ETIMEDOUT; break; @@ -153,7 +154,7 @@ mt7615_mcu_msg_send(struct mt7615_dev *dev, int cmd, const void *data, } out: - mutex_unlock(&dev->mt76.mmio.mcu.mutex); + mutex_unlock(&mdev->mmio.mcu.mutex); return ret; } @@ -171,7 +172,7 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, .mode = cpu_to_le32(mode), }; - return mt7615_mcu_msg_send(dev, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, &req, sizeof(req), true); } @@ -212,13 +213,13 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, .addr = cpu_to_le32(addr), }; - return mt7615_mcu_msg_send(dev, -MCU_CMD_FW_START_REQ, + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, &req, sizeof(req), true); } static int mt7615_mcu_restart(struct mt7615_dev *dev) { - return mt7615_mcu_msg_send(dev, -MCU_CMD_RESTART_DL_REQ, + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_RESTART_DL_REQ, NULL, 0, true); } @@ -230,7 +231,7 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - return mt7615_mcu_msg_send(dev, -MCU_CMD_PATCH_SEM_CONTROL, + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, &req, sizeof(req), true); } @@ -243,7 +244,7 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) .check_crc = 0, }; - return mt7615_mcu_msg_send(dev, -MCU_CMD_PATCH_FINISH_REQ, + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, &req, sizeof(req), true); } @@ -480,8 +481,13 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) int mt7615_mcu_init(struct mt7615_dev *dev) { + static const struct mt76_mcu_ops mt7615_mcu_ops = { + .mcu_send_msg = mt7615_mcu_msg_send, + }; int ret; + dev->mt76.mcu_ops = &mt7615_mcu_ops, + ret = mt7615_driver_own(dev); if (ret) return ret; @@ -523,7 +529,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, __MT_EE_MAX - MT_EE_NIC_CONF_0); - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, req, len, true); kfree(req); @@ -541,7 +547,7 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) .band = 0, }; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_MAC_INIT_CTRL, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, &req, sizeof(req), true); } @@ -560,7 +566,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) .pkt_thresh = cpu_to_le32(0x2), }; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_PROTECT_CTRL, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, &req, sizeof(req), true); } @@ -597,7 +603,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, req.cw_max = cpu_to_le16(params->cw_max); } - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_EDCA_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, sizeof(req), true); } @@ -627,7 +633,7 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) .band_idx = 0, }; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_PM_STATE_CTRL, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, sizeof(req), true); } @@ -666,7 +672,7 @@ int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, }; memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_DEV_INFO_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, &data, sizeof(data), true); } @@ -812,7 +818,7 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, } } - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_BSS_INFO_UPDATE, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BSS_INFO_UPDATE, buf, len, true); kfree(buf); @@ -886,7 +892,7 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, req.key.key_len = sizeof(req.key.key_material); } - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, sizeof(req), true); } @@ -919,7 +925,7 @@ mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, }; eth_broadcast_addr(req.g_wtbl.peer_addr); - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, sizeof(req), true); } @@ -934,7 +940,7 @@ int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, .operation = WTBL_RESET_AND_SET, }; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, sizeof(req), true); } @@ -973,7 +979,7 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, }; memcpy(req.g_wtbl.peer_addr, sta->addr, ETH_ALEN); - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, sizeof(req), true); } @@ -986,7 +992,7 @@ int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, .operation = WTBL_RESET_AND_SET, }; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, sizeof(req), true); } @@ -996,7 +1002,7 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) .operation = WTBL_RESET_ALL, }; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, sizeof(req), true); } @@ -1032,7 +1038,7 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, &req, sizeof(req), true); } @@ -1092,7 +1098,7 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, &req, sizeof(req), true); } @@ -1145,7 +1151,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, dev_kfree_skb(skb); - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_BCN_OFFLOAD, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req, sizeof(req), true); } @@ -1208,12 +1214,12 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) } memset(req.txpower_sku, 0x3f, 49); - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_CHANNEL_SWITCH, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, &req, sizeof(req), true); if (ret) return ret; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_SET_RX_PATH, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RX_PATH, &req, sizeof(req), true); } @@ -1299,7 +1305,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_raw->val = cpu_to_le32(val); wtbl_hdr->tlv_num = cpu_to_le16(ntlv); - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, buf, buf_len, true); if (ret) goto out; @@ -1335,7 +1341,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, cpu_to_le16(sta->vht_cap.vht_mcs.tx_mcs_map); } - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, buf, buf_len, true); out: kfree(buf); @@ -1402,12 +1408,12 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, wtbl_req.ba.ba_winsize_idx = idx; } - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &wtbl_req, sizeof(wtbl_req), true); if (ret) return ret; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, &sta_req, sizeof(sta_req), true); } @@ -1462,12 +1468,12 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, memcpy(wtbl_req.ba.peer_addr, params->sta->addr, ETH_ALEN); - ret = mt7615_mcu_msg_send(dev, MCU_EXT_CMD_STA_REC_UPDATE, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, &sta_req, sizeof(sta_req), true); if (ret || !add) return ret; - return mt7615_mcu_msg_send(dev, MCU_EXT_CMD_WTBL_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &wtbl_req, sizeof(wtbl_req), true); } From 5d15f2ea162f2d72d0673a7c4f147e9897370f2b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:08 +0200 Subject: [PATCH 24/69] mt7615: mcu: init mcu_restart function pointer Use common function wrapper in mt7615_mcu_exit since the code is shared with m7603 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index c3df9de93c8fe..cf90453c47505 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -217,10 +217,10 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, &req, sizeof(req), true); } -static int mt7615_mcu_restart(struct mt7615_dev *dev) +static int mt7615_mcu_restart(struct mt76_dev *dev) { - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_RESTART_DL_REQ, - NULL, 0, true); + return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, + 0, true); } static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) @@ -483,6 +483,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7615_mcu_ops = { .mcu_send_msg = mt7615_mcu_msg_send, + .mcu_restart = mt7615_mcu_restart, }; int ret; @@ -503,7 +504,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) void mt7615_mcu_exit(struct mt7615_dev *dev) { - mt7615_mcu_restart(dev); + __mt76_mcu_restart(&dev->mt76); mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); skb_queue_purge(&dev->mt76.mmio.mcu.res_q); } From b28248ec91955bb0c23532af912c5f8889838934 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 4 May 2019 17:29:09 +0200 Subject: [PATCH 25/69] mt7615: mcu: run __mt76_mcu_send_msg in mt7615_mcu_send_firmware Run __mt76_mcu_send_msg instead of __mt7615_mcu_msg_send and remove duplicated code. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index cf90453c47505..43f70195244c8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -179,19 +179,14 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, int len) { - struct sk_buff *skb; - int ret = 0; + int ret = 0, cur_len; while (len > 0) { - int cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), - len); - - skb = mt7615_mcu_msg_alloc(data, cur_len); - if (!skb) - return -ENOMEM; + cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), + len); - ret = __mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, - NULL); + ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, + data, cur_len, false); if (ret) break; From c38cbba4ca3161a9e53030cb2e95117fd3dec702 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 5 May 2019 02:53:32 +0200 Subject: [PATCH 26/69] mt76: mt7603: stop mac80211 queues before setting the channel Suspend data transmission during channel switch Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 0a0334dc40d54..172687a1cb15c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -207,8 +207,11 @@ mt7603_config(struct ieee80211_hw *hw, u32 changed) int ret = 0; if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | - IEEE80211_CONF_CHANGE_POWER)) + IEEE80211_CONF_CHANGE_POWER)) { + ieee80211_stop_queues(hw); ret = mt7603_set_channel(dev, &hw->conf.chandef); + ieee80211_wake_queues(hw); + } if (changed & IEEE80211_CONF_CHANGE_MONITOR) { mutex_lock(&dev->mt76.mutex); From 132191a8b8f4a2f038f71cce238b3ff8d90caba9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 5 May 2019 17:17:00 +0200 Subject: [PATCH 27/69] mt76: mt7615: rearrange cleanup operations in mt7615_unregister_device Cleanup tx/rx napi before releasing pending idrs. Moreover unmap txwi_cache running mt76_free_device routine Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 3ab3ff553ef2d..369b9a8e07be8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -212,6 +212,10 @@ void mt7615_unregister_device(struct mt7615_dev *dev) struct mt76_txwi_cache *txwi; int id; + mt76_unregister_device(&dev->mt76); + mt7615_mcu_exit(dev); + mt7615_dma_cleanup(dev); + spin_lock_bh(&dev->token_lock); idr_for_each_entry(&dev->token, txwi, id) { mt7615_txp_skb_unmap(&dev->mt76, txwi); @@ -221,9 +225,6 @@ void mt7615_unregister_device(struct mt7615_dev *dev) } spin_unlock_bh(&dev->token_lock); idr_destroy(&dev->token); - mt76_unregister_device(&dev->mt76); - mt7615_mcu_exit(dev); - mt7615_dma_cleanup(dev); - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); } From f9e5b885fab72258e7652aeea9faffb1ef118545 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 7 May 2019 11:03:33 +0200 Subject: [PATCH 28/69] mt76: mt7615: add static qualifier to mt7615_rx_poll_complete Make mt7615_rx_poll_complete static since it is used just in pci.c to initialize rx_poll_complete function pointer Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 - drivers/net/wireless/mediatek/mt76/mt7615/pci.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index e19739f9668b9..09c48dfbef3c4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -179,7 +179,6 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); -void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index e731b2bfa0291..9e82cb53fd60a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -27,7 +27,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) return MT_PCIE_REMAP_BASE_2 + offset; } -void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +static void +mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); From a78f15471c068f594a3617596f1ba12f2bddbd6e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 11 May 2019 12:17:51 +0200 Subject: [PATCH 29/69] mt76: mt76x02: remove enable from mt76x02_edcca_init signature Remove enable parameter from mt76x02_edcca_init routine signature since it is always true Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index 691984037f981..800ebbfc30553 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -33,7 +33,7 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_BUSY); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); if (mt76_is_mmio(dev)) { mt76x02_dfs_init_params(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index b1d6fd4861e32..7853078e8ca4b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -125,7 +125,7 @@ mt76_edcca_set(void *data, u64 val) dev->ed_monitor_enabled = !!val; dev->ed_monitor = dev->ed_monitor_enabled && region == NL80211_DFS_ETSI; - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 17d12d212d1ba..84b8456478813 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -887,7 +887,7 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, dev->ed_monitor = dev->ed_monitor_enabled && region == NL80211_DFS_ETSI; - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); dfs_pd->region = region; mt76x02_dfs_init_params(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 56510a1a843a8..ee4a86971be74 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -945,12 +945,12 @@ mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable) dev->ed_tx_blocked = !enable; } -void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) +void mt76x02_edcca_init(struct mt76x02_dev *dev) { dev->ed_trigger = 0; dev->ed_silent = 0; - if (dev->ed_monitor && enable) { + if (dev->ed_monitor) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index e4a9e0d0924b7..cb39da79527ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -209,5 +209,5 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, struct ieee80211_vif *vif, bool val); -void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable); +void mt76x02_edcca_init(struct mt76x02_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index cc1aebcb06966..7a39a390a7ac8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -74,7 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) mt76x2_mac_resume(dev); mt76x2_apply_gain_adj(dev); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); dev->cal.channel_cal_done = true; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 97bcf6494ec17..6657693edc3ec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -59,7 +59,7 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, err = mt76x2u_phy_set_channel(dev, chandef); mt76x2_mac_resume(dev); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); dev->beacon_ops->pre_tbtt_enable(dev, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index 07f67cb6854cd..c7208c5375ac1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -45,7 +45,7 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) if (!mac_stopped) mt76x2_mac_resume(dev); mt76x2_apply_gain_adj(dev); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); dev->cal.channel_cal_done = true; } From 842481434261e8fef7a9633f526eee4ed90db23e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 11 May 2019 12:17:52 +0200 Subject: [PATCH 30/69] mt76: mt76x2u: remove mt76x02_edcca_init in mt76x2u_set_channel Remove mt76x02_edcca_init in mt76x2u_set_channel since it is already run by mt76x2u_phy_channel_calibrate performing channel calibration Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 6657693edc3ec..3351b736603db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -59,7 +59,6 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, err = mt76x2u_phy_set_channel(dev, chandef); mt76x2_mac_resume(dev); - mt76x02_edcca_init(dev); dev->beacon_ops->pre_tbtt_enable(dev, true); From 6e4caaea99256632625fb4a3ec0557b6e5274e2d Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 11 May 2019 12:17:53 +0200 Subject: [PATCH 31/69] mt76: mt76x2: move mutex_lock inside mt76x2_set_channel This is a preliminary patch to run mt76x02_edcca_init atomically Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 16 ++++++++------ .../wireless/mediatek/mt76/mt76x2/usb_main.c | 22 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index e416eee6a306c..3a1467326f4de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -54,14 +54,14 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) int ret; cancel_delayed_work_sync(&dev->cal_work); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); + tasklet_disable(&dev->dfs_pd.dfs_tasklet); + mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); mt76_set_channel(&dev->mt76); - tasklet_disable(&dev->mt76.pre_tbtt_tasklet); - tasklet_disable(&dev->dfs_pd.dfs_tasklet); - mt76x2_mac_stop(dev, true); ret = mt76x2_phy_set_channel(dev, chandef); @@ -72,10 +72,12 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76x02_dfs_init_params(dev); mt76x2_mac_resume(dev); - tasklet_enable(&dev->dfs_pd.dfs_tasklet); - tasklet_enable(&dev->mt76.pre_tbtt_tasklet); clear_bit(MT76_RESET, &dev->mt76.state); + mutex_unlock(&dev->mt76.mutex); + + tasklet_enable(&dev->dfs_pd.dfs_tasklet); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); mt76_txq_schedule_all(&dev->mt76); @@ -111,14 +113,14 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) } } + mutex_unlock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); ret = mt76x2_set_channel(dev, &hw->conf.chandef); ieee80211_wake_queues(hw); } - mutex_unlock(&dev->mt76.mutex); - return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 3351b736603db..e4dfc3bea3c5b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -48,21 +48,23 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, int err; cancel_delayed_work_sync(&dev->cal_work); + dev->beacon_ops->pre_tbtt_enable(dev, false); + + mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); mt76_set_channel(&dev->mt76); - dev->beacon_ops->pre_tbtt_enable(dev, false); - mt76x2_mac_stop(dev, false); err = mt76x2u_phy_set_channel(dev, chandef); mt76x2_mac_resume(dev); - dev->beacon_ops->pre_tbtt_enable(dev, true); - clear_bit(MT76_RESET, &dev->mt76.state); + mutex_unlock(&dev->mt76.mutex); + + dev->beacon_ops->pre_tbtt_enable(dev, true); mt76_txq_schedule_all(&dev->mt76); return err; @@ -84,12 +86,6 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter); } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - err = mt76x2u_set_channel(dev, &hw->conf.chandef); - ieee80211_wake_queues(hw); - } - if (changed & IEEE80211_CONF_CHANGE_POWER) { dev->mt76.txpower_conf = hw->conf.power_level * 2; @@ -102,6 +98,12 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + ieee80211_stop_queues(hw); + err = mt76x2u_set_channel(dev, &hw->conf.chandef); + ieee80211_wake_queues(hw); + } + return err; } From 8aac454dbb51387a3429ab88993878193381a7cc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 11 May 2019 17:30:10 +0200 Subject: [PATCH 32/69] mt76: mt76x02: run mt76x02_edcca_init atomically in mt76_edcca_set Run mt76x02_edcca_init atomically in mt76_edcca_set since it runs concurrently with calibration work and mt76x2_set_channel. Moreover perform phy calibration atomically Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c | 4 ++++ drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index 7853078e8ca4b..f412c779d8e26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -122,11 +122,15 @@ mt76_edcca_set(void *data, u64 val) struct mt76x02_dev *dev = data; enum nl80211_dfs_regions region = dev->dfs_pd.region; + mutex_lock(&dev->mt76.mutex); + dev->ed_monitor_enabled = !!val; dev->ed_monitor = dev->ed_monitor_enabled && region == NL80211_DFS_ETSI; mt76x02_edcca_init(dev); + mutex_unlock(&dev->mt76.mutex); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 7a39a390a7ac8..2edf1bd0c18cb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -294,10 +294,16 @@ void mt76x2_phy_calibrate(struct work_struct *work) struct mt76x02_dev *dev; dev = container_of(work, struct mt76x02_dev, cal_work.work); + + mutex_lock(&dev->mt76.mutex); + mt76x2_phy_channel_calibrate(dev, false); mt76x2_phy_tssi_compensate(dev); mt76x2_phy_temp_compensate(dev); mt76x2_phy_update_channel_gain(dev); + + mutex_unlock(&dev->mt76.mutex); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index c7208c5375ac1..dfd54f9b0e97f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -55,10 +55,15 @@ void mt76x2u_phy_calibrate(struct work_struct *work) struct mt76x02_dev *dev; dev = container_of(work, struct mt76x02_dev, cal_work.work); + + mutex_lock(&dev->mt76.mutex); + mt76x2u_phy_channel_calibrate(dev, false); mt76x2_phy_tssi_compensate(dev); mt76x2_phy_update_channel_gain(dev); + mutex_unlock(&dev->mt76.mutex); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); } From 984d885437f10bc0785bec10f31678349b5b2659 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 13 May 2019 12:19:35 +0200 Subject: [PATCH 33/69] mt76: mt7603: add debugfs knob to enable/disable edcca Introduce a knob in mt7603 debugfs in order to enable/disable energy detection based on CCA thresholds Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7603/debugfs.c | 30 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7603/init.c | 4 ++- .../net/wireless/mediatek/mt76/mt7603/main.c | 3 +- .../wireless/mediatek/mt76/mt7603/mt7603.h | 6 +++- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c index f8b3b6ab62979..9c0bea489e1fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c @@ -40,6 +40,35 @@ mt7603_radio_read(struct seq_file *s, void *data) return 0; } +static int +mt7603_edcca_set(void *data, u64 val) +{ + struct mt7603_dev *dev = data; + + mutex_lock(&dev->mt76.mutex); + + dev->ed_monitor_enabled = !!val; + dev->ed_monitor = dev->ed_monitor_enabled && + dev->region == NL80211_DFS_ETSI; + mt7603_init_edcca(dev); + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static int +mt7603_edcca_get(void *data, u64 *val) +{ + struct mt7603_dev *dev = data; + + *val = dev->ed_monitor_enabled; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_edcca, mt7603_edcca_get, + mt7603_edcca_set, "%lld\n"); + void mt7603_init_debugfs(struct mt7603_dev *dev) { struct dentry *dir; @@ -48,6 +77,7 @@ void mt7603_init_debugfs(struct mt7603_dev *dev) if (!dir) return; + debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca); debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir, mt7603_reset_read); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 78cdbb70e1789..4e269044f8a44 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -437,7 +437,9 @@ mt7603_regd_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7603_dev *dev = hw->priv; - dev->ed_monitor = request->dfs_region == NL80211_DFS_ETSI; + dev->region = request->dfs_region; + dev->ed_monitor = dev->ed_monitor_enabled && + dev->region == NL80211_DFS_ETSI; } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 172687a1cb15c..e5d4cb6381a8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -103,8 +103,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_unlock(&dev->mt76.mutex); } -static void -mt7603_init_edcca(struct mt7603_dev *dev) +void mt7603_init_edcca(struct mt7603_dev *dev) { /* Set lower signal level to -65dBm */ mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index fa64bbaab0d2c..944dc9a11a153 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -117,8 +117,11 @@ struct mt7603_dev { u8 mac_work_count; u8 mcu_running; - u8 ed_monitor; + enum nl80211_dfs_regions region; + + u8 ed_monitor_enabled; + u8 ed_monitor; s8 ed_trigger; u8 ed_strict_mode; u8 ed_strong_signal; @@ -241,4 +244,5 @@ void mt7603_update_channel(struct mt76_dev *mdev); void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val); void mt7603_cca_stats_reset(struct mt7603_dev *dev); +void mt7603_init_edcca(struct mt7603_dev *dev); #endif From 4a8c99c73777afd2fe785a39ffd2dd44f7c21d27 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 13 May 2019 12:23:29 +0200 Subject: [PATCH 34/69] mt76: mt76x02: fix edcca file permission Use 0600 as edcca file permission in mt76x02 debugfs Fixes: 643749d4a82b ("mt76: mt76x02: disable ED/CCA by default") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index f412c779d8e26..ffdba5ffc22df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -157,7 +157,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev) debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp); debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc); - debugfs_create_file("edcca", 0400, dir, dev, &fops_edcca); + debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir, From 2dcb79cde6129d948a237ef7b48a73a0c82f1e01 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 14 May 2019 11:18:52 +0200 Subject: [PATCH 35/69] mt76: mt7615: do not process rx packets if the device is not initialized Fix following crash that occurs when the driver is processing rx packets while the device is not initialized yet $ rmmod mt7615e [ 67.210261] mt7615e 0000:01:00.0: Message -239 (seq 2) timeout $ modprobe mt7615e [ 72.406937] bus=0x1, slot = 0x0, irq=0x16 [ 72.436590] CPU 0 Unable to handle kernel paging request at virtual address 00000004, epc == 8eec4240, ra == 8eec41e0 [ 72.450291] mt7615e 0000:01:00.0: Firmware is not ready for download [ 72.457724] Oops[#1]: [ 72.470494] mt7615e: probe of 0000:01:00.0 failed with error -5 [ 72.474829] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.14.114 #0 [ 72.498702] task: 805769e0 task.stack: 80564000 [ 72.507709] $ 0 : 00000000 00000001 00000000 00000001 [ 72.518106] $ 4 : 8f704dbc 00000000 00000000 8f7046c0 [ 72.528500] $ 8 : 00000024 8045e98c 81210008 11000000 [ 72.538895] $12 : 8fc09f60 00000008 00000019 00000033 [ 72.549289] $16 : 8f704d80 e00000ff 8f0c7800 3c182406 [ 72.559684] $20 : 00000006 8ee615a0 4e000108 00000000 [ 72.570078] $24 : 0000004c 8000cf94 [ 72.580474] $28 : 80564000 8fc09e38 00000001 8eec41e0 [ 72.590869] Hi : 00000001 [ 72.596582] Lo : 00000000 [ 72.602319] epc : 8eec4240 mt7615_mac_fill_rx+0xac/0x494 [mt7615e] [ 72.614953] ra : 8eec41e0 mt7615_mac_fill_rx+0x4c/0x494 [mt7615e] [ 72.627580] Status: 11008403 KERNEL EXL IE [ 72.635899] Cause : 40800008 (ExcCode 02) [ 72.643860] BadVA : 00000004 [ 72.649573] PrId : 0001992f (MIPS 1004Kc) [ 72.657704] Modules linked in: mt7615e pppoe ppp_async pppox ppp_generic nf_conntrack_ipv6 mt76x2e mt76x2_common mt76x02_lib mt7603e mt76 mac80211 iptable_nat ipt_REJECT ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_nat xt_mu] [ 72.792717] Process swapper/0 (pid: 0, threadinfo=80564000, task=805769e0, tls=00000000) [ 72.808799] Stack : 8f0c7800 00000800 8f0c7800 8032b874 00000000 40000000 8f704d80 8ee615a0 [ 72.825428] 8dc88010 00000001 8ee615e0 8eec09b0 8dc88010 8032b914 8f3aee80 80567d20 [ 72.842055] 00000000 8ee615e0 40000000 8f0c7800 00000108 8eec9944 00000000 00000000 [ 72.858682] 80508f10 80510000 00000001 80567d20 8ee615a0 00000000 00000000 8ee61c00 [ 72.875308] 8ee61c40 00000040 80610000 80580000 00000000 8ee615dc 8ee61a68 00000001 [ 72.891936] ... [ 72.896793] Call Trace: [ 72.901649] [<8eec4240>] mt7615_mac_fill_rx+0xac/0x494 [mt7615e] [ 72.913602] [<8eec09b0>] mt7615_queue_rx_skb+0xe4/0x12c [mt7615e] [ 72.925734] [<8eec9944>] mt76_dma_cleanup+0x390/0x42c [mt76] [ 72.936988] Code: ae020018 8ea20004 24030001 <94420004> a602002a 8ea20004 90420000 14430003 a2020034 [ 72.956390] [ 72.959676] ---[ end trace f176967739edb19f ]--- Fixes: 04b8e65922f6 ("mt76: add mac80211 driver for MT7615 PCIe-based chipsets") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index b8f48d10f27a5..a27bc6791aa7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -96,6 +96,9 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) bool unicast, remove_pad, insert_ccmp_hdr = false; int i, idx; + if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + return -EINVAL; + memset(status, 0, sizeof(*status)); unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; From b0297b6738b20d6e6e4dfa7d5f73d544ffba0f4d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 31 May 2019 22:02:17 +0200 Subject: [PATCH 36/69] mt76: mt7603: fix reading target tx power from eeprom For the external PA (TSSI OFF) case, the target power needs to be read from a different location in EEPROM Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h | 2 ++ drivers/net/wireless/mediatek/mt76/mt7603/init.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h index f27b99b7e359b..b893facfba480 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h @@ -69,6 +69,8 @@ enum mt7603_eeprom_field { MT_EE_CP_FT_VERSION = 0x0f0, + MT_EE_TX_POWER_TSSI_OFF = 0x0f2, + MT_EE_XTAL_FREQ_OFFSET = 0x0f4, MT_EE_XTAL_TRIM_2_COMP = 0x0f5, MT_EE_XTAL_TRIM_3_COMP = 0x0f6, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 4e269044f8a44..43baad7fd0829 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -465,9 +465,13 @@ mt7603_init_txpower(struct mt7603_dev *dev, u8 *eeprom = (u8 *)dev->mt76.eeprom.data; int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7); u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK]; + bool ext_pa = eeprom[MT_EE_NIC_CONF_0 + 1] & BIT(1); int max_offset, cur_offset; int i; + if (ext_pa && is_mt7603(dev)) + target_power = eeprom[MT_EE_TX_POWER_TSSI_OFF] & ~BIT(7); + if (target_power & BIT(6)) target_power = -(target_power & GENMASK(5, 0)); From 0995257242ebe8439df09fc7c2ff312ccf183754 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 31 May 2019 22:03:11 +0200 Subject: [PATCH 37/69] mt76: fix setting chan->max_power When setting chan->max_power after registering the wiphy, chan->max_reg_power needs to be used as a limit Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 5 +++-- drivers/net/wireless/mediatek/mt76/mt76x2/init.c | 9 +++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 43baad7fd0829..f655091d106b4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -494,7 +494,7 @@ mt7603_init_txpower(struct mt7603_dev *dev, for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; - chan->max_power = target_power; + chan->max_power = min_t(int, chan->max_reg_power, target_power); chan->orig_mpwr = target_power; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 57e46d57b4494..d67401f895ca1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -279,8 +279,9 @@ mt76x0_init_txpower(struct mt76x02_dev *dev, mt76x0_get_tx_power_per_rate(dev, chan, &t); mt76x0_get_power_info(dev, chan, &tp); - chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2; - chan->orig_mpwr = chan->max_power; + chan->orig_mpwr = (mt76x02_get_max_rate_power(&t) + tp) / 2; + chan->max_power = min_t(int, chan->max_reg_power, + chan->orig_mpwr); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index c6078e90ca434..97c3543eed8ab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -173,13 +173,14 @@ void mt76x2_init_txpower(struct mt76x02_dev *dev, mt76x2_get_power_info(dev, &txp, chan); mt76x2_get_rate_power(dev, &t, chan); - chan->max_power = mt76x02_get_max_rate_power(&t) + + chan->orig_mpwr = mt76x02_get_max_rate_power(&t) + txp.target_power; - chan->max_power = DIV_ROUND_UP(chan->max_power, 2); + chan->orig_mpwr = DIV_ROUND_UP(chan->orig_mpwr, 2); /* convert to combined output power on 2x2 devices */ - chan->max_power += 3; - chan->orig_mpwr = chan->max_power; + chan->orig_mpwr += 3; + chan->max_power = min_t(int, chan->max_reg_power, + chan->orig_mpwr); } } EXPORT_SYMBOL_GPL(mt76x2_init_txpower); From 8548c6eb23d29078bba41e3477873e4ad340adee Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 5 Jun 2019 20:50:52 +0200 Subject: [PATCH 38/69] mt76: mt76x02: fix tx status reporting issues When the hardware falls back to lower rates for a transmit attempt, only the first status report will show the number of retries correctly. The frames that follow will report the correct final rate, but number of retries set to 0. This can cause the rate control module to vastly underestimate the number of retransmissions per rate. To fix this, we need to keep track of the initial requested tx rate per packet and pass it to the status information. For frames with tx status requested, this is simple: use the rate configured in info->control.rates[0] as reference. For no-skb tx status information, we have to encode the requested tx rate in the packet id (and make it possible to distinguish it from real packet ids). To do that, reduce the packet id field size by one bit, and use that bit to indicate packet id vs rate. This change also improves reporting by filling the status rate array with rates from first rate to final rate, taking the same steps as the hardware fallback table. This matters in corner cases like MCS8 on HT, where the fallback target is MCS0, not MCS7. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 11 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 102 +++++++++++++++--- .../net/wireless/mediatek/mt76/mt76x02_txrx.c | 8 +- .../wireless/mediatek/mt76/mt76x02_usb_core.c | 8 +- 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index fc4169c83e764..907bec9d5e4c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -258,10 +258,11 @@ struct mt76_rx_tid { #define MT_TX_CB_TXS_DONE BIT(1) #define MT_TX_CB_TXS_FAILED BIT(2) -#define MT_PACKET_ID_MASK GENMASK(7, 0) +#define MT_PACKET_ID_MASK GENMASK(6, 0) #define MT_PACKET_ID_NO_ACK 0 #define MT_PACKET_ID_NO_SKB 1 #define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) #define MT_TX_STATUS_SKB_TIMEOUT HZ @@ -689,6 +690,14 @@ static inline void mt76_insert_hdr_pad(struct sk_buff *skb) skb->data[len + 1] = 0; } +static inline bool mt76_is_skb_pktid(u8 pktid) +{ + if (pktid & MT_PACKET_ID_HAS_RATE) + return false; + + return pktid >= MT_PACKET_ID_FIRST; +} + void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index ee4a86971be74..82bafb5ac3265 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -420,30 +420,92 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, EXPORT_SYMBOL_GPL(mt76x02_mac_write_txwi); static void -mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, +mt76x02_tx_rate_fallback(struct ieee80211_tx_rate *rates, int idx, int phy) +{ + u8 mcs, nss; + + if (!idx) + return; + + rates += idx - 1; + rates[1] = rates[0]; + switch (phy) { + case MT_PHY_TYPE_VHT: + mcs = ieee80211_rate_get_vht_mcs(rates); + nss = ieee80211_rate_get_vht_nss(rates); + + if (mcs == 0) + nss = max_t(int, nss - 1, 1); + else + mcs--; + + ieee80211_rate_set_vht(rates + 1, mcs, nss); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + /* MCS 8 falls back to MCS 0 */ + if (rates[0].idx == 8) { + rates[1].idx = 0; + break; + } + /* fall through */ + default: + rates[1].idx = max_t(int, rates[0].idx - 1, 0); + break; + } +} + +static void +mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, struct mt76x02_sta *msta, struct ieee80211_tx_info *info, struct mt76x02_tx_status *st, int n_frames) { struct ieee80211_tx_rate *rate = info->status.rates; - int cur_idx, last_rate; + struct ieee80211_tx_rate last_rate; + u16 first_rate; + int retry = st->retry; + int phy; int i; if (!n_frames) return; - last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1); - mt76x02_mac_process_tx_rate(&rate[last_rate], st->rate, + phy = FIELD_GET(MT_RXWI_RATE_PHY, st->rate); + + if (st->pktid & MT_PACKET_ID_HAS_RATE) { + first_rate = st->rate & ~MT_RXWI_RATE_INDEX; + first_rate |= st->pktid & MT_RXWI_RATE_INDEX; + + mt76x02_mac_process_tx_rate(&rate[0], first_rate, + dev->mt76.chandef.chan->band); + } else if (rate[0].idx < 0) { + if (!msta) + return; + + mt76x02_mac_process_tx_rate(&rate[0], msta->wcid.tx_info, + dev->mt76.chandef.chan->band); + } + + mt76x02_mac_process_tx_rate(&last_rate, st->rate, dev->mt76.chandef.chan->band); - if (last_rate < IEEE80211_TX_MAX_RATES - 1) - rate[last_rate + 1].idx = -1; - - cur_idx = rate[last_rate].idx + last_rate; - for (i = 0; i <= last_rate; i++) { - rate[i].flags = rate[last_rate].flags; - rate[i].idx = max_t(int, 0, cur_idx - i); - rate[i].count = 1; + + for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { + retry--; + if (i + 1 == ARRAY_SIZE(info->status.rates)) { + info->status.rates[i] = last_rate; + info->status.rates[i].count = max_t(int, retry, 1); + break; + } + + mt76x02_tx_rate_fallback(info->status.rates, i, phy); + if (info->status.rates[i].idx == last_rate.idx) + break; + } + + if (i + 1 < ARRAY_SIZE(info->status.rates)) { + info->status.rates[i + 1].idx = -1; + info->status.rates[i + 1].count = 0; } - rate[last_rate].count = st->retry + 1 - last_rate; info->status.ampdu_len = n_frames; info->status.ampdu_ack_len = st->success ? n_frames : 0; @@ -489,13 +551,19 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, mt76_tx_status_lock(mdev, &list); if (wcid) { - if (stat->pktid >= MT_PACKET_ID_FIRST) + if (mt76_is_skb_pktid(stat->pktid)) status.skb = mt76_tx_status_skb_get(mdev, wcid, stat->pktid, &list); if (status.skb) status.info = IEEE80211_SKB_CB(status.skb); } + if (!status.skb && !(stat->pktid & MT_PACKET_ID_HAS_RATE)) { + mt76_tx_status_unlock(mdev, &list); + rcu_read_unlock(); + return; + } + if (msta && stat->aggr && !status.skb) { u32 stat_val, stat_cache; @@ -512,14 +580,14 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, return; } - mt76x02_mac_fill_tx_status(dev, status.info, &msta->status, - msta->n_frames); + mt76x02_mac_fill_tx_status(dev, msta, status.info, + &msta->status, msta->n_frames); msta->status = *stat; msta->n_frames = 1; *update = 0; } else { - mt76x02_mac_fill_tx_status(dev, status.info, stat, 1); + mt76x02_mac_fill_tx_status(dev, msta, status.info, stat, 1); *update = 1; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index cf7abd9b7d2ea..7a1164a07ee75 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -164,9 +164,15 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len); pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + + /* encode packet rate for no-skb packet id to fix up status reporting */ + if (pid == MT_PACKET_ID_NO_SKB) + pid = MT_PACKET_ID_HAS_RATE | + (le16_to_cpu(txwi->rate) & MT_RXWI_RATE_INDEX); + txwi->pktid = pid; - if (pid >= MT_PACKET_ID_FIRST) + if (mt76_is_skb_pktid(pid)) qsel = MT_QSEL_MGMT; tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 6b89f7eab26c9..47386ca713cc9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -89,9 +89,15 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, skb_push(tx_info->skb, sizeof(*txwi)); pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + + /* encode packet rate for no-skb packet id to fix up status reporting */ + if (pid == MT_PACKET_ID_NO_SKB) + pid = MT_PACKET_ID_HAS_RATE | + (le16_to_cpu(txwi->rate) & MT_RXWI_RATE_INDEX); + txwi->pktid = pid; - if (pid >= MT_PACKET_ID_FIRST || ep == MT_EP_OUT_HCCA) + if (mt76_is_skb_pktid(pid) || ep == MT_EP_OUT_HCCA) qsel = MT_QSEL_MGMT; else qsel = MT_QSEL_EDCA; From 5c280ae76795f0da5cb89e19101cb520374aad7f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 6 Jun 2019 09:22:15 +0200 Subject: [PATCH 39/69] mt76: mt76x02: fix tx reordering on rate control probing without a-mpdu To avoid aggregating rate control probing packets with other traffic, and to ensure that the probing rate gets used, probing packets get assigned a different internal queueing priority. This causes packets to be transmitted in a different order, which is compensated by the receiver side reordering. However, if A-MPDU is disabled, this reordering can become visible to upper layers on the receiver side. Disable the priority change if A-MPDU is disabled. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 3 ++- drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 7a1164a07ee75..04118f08debcb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -154,6 +154,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt76x02_txwi *txwi = txwi_ptr; + bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; int hdrlen, len, pid, qsel = MT_QSEL_EDCA; if (qid == MT_TXQ_PSD && wcid && wcid->idx < 128) @@ -172,7 +173,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, txwi->pktid = pid; - if (mt76_is_skb_pktid(pid)) + if (mt76_is_skb_pktid(pid) && ampdu) qsel = MT_QSEL_MGMT; tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 47386ca713cc9..42ec02b6cdd6c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -79,6 +79,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx); struct mt76x02_txwi *txwi; + bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; enum mt76_qsel qsel; u32 flags; @@ -97,7 +98,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, txwi->pktid = pid; - if (mt76_is_skb_pktid(pid) || ep == MT_EP_OUT_HCCA) + if ((mt76_is_skb_pktid(pid) && ampdu) || ep == MT_EP_OUT_HCCA) qsel = MT_QSEL_MGMT; else qsel = MT_QSEL_EDCA; From eadfd98f40255cca136853a3e81bf4dd9fd1d8af Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 14 May 2019 14:48:31 +0200 Subject: [PATCH 40/69] mt76: move mt76_insert_ccmp_hdr in mt76-module Move mt7615_insert_ccmp_hdr in mac80211.c and rename it in mt76_insert_ccmp_hdr since it is shared between mt7603 and mt7615 drivers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 23 ++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7603/mac.c | 26 +------------------ .../net/wireless/mediatek/mt76/mt7615/mac.c | 25 +----------------- 4 files changed, 26 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 5b6a81ee457e9..e70507a4b14dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -820,3 +820,26 @@ mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) return 0; } EXPORT_SYMBOL_GPL(mt76_set_tim); + +void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + int hdr_len = ieee80211_get_hdrlen_from_skb(skb); + u8 *hdr, *pn = status->iv; + + __skb_push(skb, 8); + memmove(skb->data, skb->data + 8, hdr_len); + hdr = skb->data + hdr_len; + + hdr[0] = pn[5]; + hdr[1] = pn[4]; + hdr[2] = 0; + hdr[3] = 0x20 | (key_id << 6); + hdr[4] = pn[3]; + hdr[5] = pn[2]; + hdr[6] = pn[1]; + hdr[7] = pn[0]; + + status->flag &= ~RX_FLAG_IV_STRIPPED; +} +EXPORT_SYMBOL_GPL(mt76_insert_ccmp_hdr); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 907bec9d5e4c1..eef0e5aa6dd0c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -759,6 +759,7 @@ void mt76_csa_check(struct mt76_dev *dev); void mt76_csa_finish(struct mt76_dev *dev); int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); +void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id); /* internal */ void mt76_tx_free(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 0ccba5926b684..5c09b2dbf3fda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -418,30 +418,6 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) return &sta->vif->sta.wcid; } -static void -mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - int hdr_len = ieee80211_get_hdrlen_from_skb(skb); - u8 *pn = status->iv; - u8 *hdr; - - __skb_push(skb, 8); - memmove(skb->data, skb->data + 8, hdr_len); - hdr = skb->data + hdr_len; - - hdr[0] = pn[5]; - hdr[1] = pn[4]; - hdr[2] = 0; - hdr[3] = 0x20 | (key_id << 6); - hdr[4] = pn[3]; - hdr[5] = pn[2]; - hdr[6] = pn[1]; - hdr[7] = pn[0]; - - status->flag &= ~RX_FLAG_IV_STRIPPED; -} - int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) { @@ -580,7 +556,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); - mt7603_insert_ccmp_hdr(skb, key_id); + mt76_insert_ccmp_hdr(skb, key_id); } hdr = (struct ieee80211_hdr *)skb->data; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index a27bc6791aa7d..1547bce561d38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -61,29 +61,6 @@ static int mt7615_get_rate(struct mt7615_dev *dev, return 0; } -static void mt7615_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - int hdr_len = ieee80211_get_hdrlen_from_skb(skb); - u8 *pn = status->iv; - u8 *hdr; - - __skb_push(skb, 8); - memmove(skb->data, skb->data + 8, hdr_len); - hdr = skb->data + hdr_len; - - hdr[0] = pn[5]; - hdr[1] = pn[4]; - hdr[2] = 0; - hdr[3] = 0x20 | (key_id << 6); - hdr[4] = pn[3]; - hdr[5] = pn[2]; - hdr[6] = pn[1]; - hdr[7] = pn[0]; - - status->flag &= ~RX_FLAG_IV_STRIPPED; -} - int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -228,7 +205,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); - mt7615_insert_ccmp_hdr(skb, key_id); + mt76_insert_ccmp_hdr(skb, key_id); } hdr = (struct ieee80211_hdr *)skb->data; From f9461a687928df2f749e99739d37da440efcf385 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 17 May 2019 08:26:05 +0200 Subject: [PATCH 41/69] mt76: mt7615: add support for mtd eeprom parsing Calibration data are often available on a specific mtd partition on embedded devices. Take into account eeprom calibration data if available. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/eeprom.c | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index dd5ab46a4f662..1712f66520a81 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -42,13 +42,13 @@ static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base, static int mt7615_efuse_init(struct mt7615_dev *dev) { - u32 base = mt7615_reg_map(dev, MT_EFUSE_BASE); - int len = MT7615_EEPROM_SIZE; - int ret, i; + u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE); + int i, len = MT7615_EEPROM_SIZE; void *buf; - if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY) - return -EINVAL; + val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL); + if (val & MT_EFUSE_BASE_CTRL_EMPTY) + return 0; dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); dev->mt76.otp.size = len; @@ -57,6 +57,8 @@ static int mt7615_efuse_init(struct mt7615_dev *dev) buf = dev->mt76.otp.data; for (i = 0; i + 16 <= len; i += 16) { + int ret; + ret = mt7615_efuse_read(dev, base, i, buf + i); if (ret) return ret; @@ -76,6 +78,18 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev) return mt7615_efuse_init(dev); } +static int mt7615_check_eeprom(struct mt76_dev *dev) +{ + u16 val = get_unaligned_le16(dev->eeprom.data); + + switch (val) { + case 0x7615: + return 0; + default: + return -EINVAL; + } +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -84,7 +98,10 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) if (ret < 0) return ret; - memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); + ret = mt7615_check_eeprom(&dev->mt76); + if (ret && dev->mt76.otp.data) + memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, + MT7615_EEPROM_SIZE); dev->mt76.cap.has_2ghz = true; dev->mt76.cap.has_5ghz = true; From c988a77f1de523ed75a410d96a2e7a969b5e4a01 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 17 May 2019 23:32:56 +0200 Subject: [PATCH 42/69] mt76: mt7615: select wifi band according to eeprom Select supported band according to the value read from eeprom mtd/otp partition Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/eeprom.c | 24 ++++++++++++++++--- .../wireless/mediatek/mt76/mt7615/eeprom.h | 9 +++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 1712f66520a81..714590878d658 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -90,6 +90,26 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) } } +static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) +{ + u8 val, *eeprom = dev->mt76.eeprom.data; + + val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, + eeprom[MT_EE_WIFI_CONF]); + switch (val) { + case MT_EE_5GHZ: + dev->mt76.cap.has_5ghz = true; + break; + case MT_EE_2GHZ: + dev->mt76.cap.has_2ghz = true; + break; + default: + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; + break; + } +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -103,9 +123,7 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; - + mt7615_eeprom_parse_hw_cap(dev); memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index a4cf166881717..b422e395d6ee7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -11,8 +11,17 @@ enum mt7615_eeprom_field { MT_EE_VERSION = 0x002, MT_EE_MAC_ADDR = 0x004, MT_EE_NIC_CONF_0 = 0x034, + MT_EE_WIFI_CONF = 0x03e, __MT_EE_MAX = 0x3bf }; +#define MT_EE_NIC_WIFI_CONF_BAND_SEL GENMASK(5, 4) +enum mt7615_eeprom_band { + MT_EE_DUAL_BAND, + MT_EE_5GHZ, + MT_EE_2GHZ, + MT_EE_DBDC, +}; + #endif From c19b0ca503a855f41358f98ac533d2a4e867fe34 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 26 May 2019 16:05:10 +0200 Subject: [PATCH 43/69] mt76: generalize mt76_get_txpower for 4x4:4 devices Genralize mt76_get_txpower routine for 4x4:4 capable devices in order to be reused in mt7615 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index e70507a4b14dc..f9e83971902ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -766,10 +766,21 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, *dbm = DIV_ROUND_UP(dev->txpower_cur, 2); /* convert from per-chain power to combined - * output on 2x2 devices + * output power */ - if (n_chains > 1) + switch (n_chains) { + case 4: + *dbm += 6; + break; + case 3: + *dbm += 4; + break; + case 2: *dbm += 3; + break; + default: + break; + } return 0; } From 61d368247ec1ae1dee241a5bcf747591104ac67a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 26 May 2019 16:05:11 +0200 Subject: [PATCH 44/69] mt76: mt7615: add the capability to configure tx power Introduce mt7615_mcu_set_tx_power routine in order to cap tx power according to the value configured by the user Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/eeprom.c | 34 ++++++++++ .../wireless/mediatek/mt76/mt7615/eeprom.h | 35 ++++++++++ .../net/wireless/mediatek/mt76/mt7615/main.c | 3 + .../net/wireless/mediatek/mt76/mt7615/mcu.c | 64 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.h | 1 + .../wireless/mediatek/mt76/mt7615/mt7615.h | 3 + 6 files changed, 140 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 714590878d658..023c8bbc767dd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -110,6 +110,40 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) } } +int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan, + u8 chain_idx) +{ + int index; + + if (chain_idx > 3) + return -EINVAL; + + if (chan->band == NL80211_BAND_2GHZ) { + index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6; + } else { + int group = mt7615_get_channel_group(chan->hw_value); + + switch (chain_idx) { + case 1: + index = MT_EE_TX1_5G_G0_TARGET_POWER; + break; + case 2: + index = MT_EE_TX2_5G_G0_TARGET_POWER; + break; + case 3: + index = MT_EE_TX3_5G_G0_TARGET_POWER; + break; + case 0: + default: + index = MT_EE_TX0_5G_G0_TARGET_POWER; + break; + } + index += 5 * group; + } + + return index; +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index b422e395d6ee7..3c9086b67f515 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -12,6 +12,11 @@ enum mt7615_eeprom_field { MT_EE_MAC_ADDR = 0x004, MT_EE_NIC_CONF_0 = 0x034, MT_EE_WIFI_CONF = 0x03e, + MT_EE_TX0_2G_TARGET_POWER = 0x058, + MT_EE_TX0_5G_G0_TARGET_POWER = 0x070, + MT_EE_TX1_5G_G0_TARGET_POWER = 0x098, + MT_EE_TX2_5G_G0_TARGET_POWER = 0x142, + MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a, __MT_EE_MAX = 0x3bf }; @@ -24,4 +29,34 @@ enum mt7615_eeprom_band { MT_EE_DBDC, }; +enum mt7615_channel_group { + MT_CH_5G_JAPAN, + MT_CH_5G_UNII_1, + MT_CH_5G_UNII_2A, + MT_CH_5G_UNII_2B, + MT_CH_5G_UNII_2E_1, + MT_CH_5G_UNII_2E_2, + MT_CH_5G_UNII_2E_3, + MT_CH_5G_UNII_3, + __MT_CH_MAX +}; + +static inline enum mt7615_channel_group +mt7615_get_channel_group(int channel) +{ + if (channel >= 184 && channel <= 196) + return MT_CH_5G_JAPAN; + if (channel <= 48) + return MT_CH_5G_UNII_1; + if (channel <= 64) + return MT_CH_5G_UNII_2A; + if (channel <= 114) + return MT_CH_5G_UNII_2E_1; + if (channel <= 144) + return MT_CH_5G_UNII_2E_2; + if (channel <= 161) + return MT_CH_5G_UNII_2E_3; + return MT_CH_5G_UNII_3; +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index b0bb7cc123854..72bdb871ca138 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -201,6 +201,9 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&dev->mt76.mutex); } + if (changed & IEEE80211_CONF_CHANGE_POWER) + ret = mt7615_mcu_set_tx_power(dev); + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { mutex_lock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 43f70195244c8..0e12e9f05f95c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1151,6 +1151,70 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, &req, sizeof(req), true); } +int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) +{ + int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); + struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; + struct ieee80211_hw *hw = mt76_hw(dev); + int freq = chandef->center_freq1, len; + struct { + u8 center_chan; + u8 dbdc_idx; + u8 band; + u8 rsv; + } __packed req_hdr = { + .center_chan = ieee80211_frequency_to_channel(freq), + .band = chandef->chan->band, + }; + s8 tx_power; + + len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + req = kzalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; + + memcpy(req, &req_hdr, sizeof(req_hdr)); + data = req + sizeof(req_hdr); + memcpy(data, eep + MT_EE_NIC_CONF_0, + __MT_EE_MAX - MT_EE_NIC_CONF_0); + + tx_power = hw->conf.power_level * 2; + switch (n_chains) { + case 4: + tx_power -= 12; + break; + case 3: + tx_power -= 8; + break; + case 2: + tx_power -= 6; + break; + default: + break; + } + tx_power = max_t(s8, tx_power, 0); + dev->mt76.txpower_cur = tx_power; + + for (i = 0; i < n_chains; i++) { + int index = -MT_EE_NIC_CONF_0; + + ret = mt7615_eeprom_get_power_index(chandef->chan, i); + if (ret < 0) + goto out; + + index += ret; + data[index] = min_t(u8, data[index], tx_power); + } + + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, + req, len, true); +out: + kfree(req); + + return ret; +} + int mt7615_mcu_set_channel(struct mt7615_dev *dev) { struct cfg80211_chan_def *chdef = &dev->mt76.chandef; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index e96efb13fa4d0..cca11737693c0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -70,6 +70,7 @@ enum { enum { MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, + MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, MCU_EXT_CMD_STA_REC_UPDATE = 0x25, MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 09c48dfbef3c4..7c08d3b93a2a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -105,6 +105,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); +int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan, + u8 chain_idx); int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); @@ -167,6 +169,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); int mt7615_mcu_init_mac(struct mt7615_dev *dev); int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); +int mt7615_mcu_set_tx_power(struct mt7615_dev *dev); void mt7615_mcu_exit(struct mt7615_dev *dev); int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, From 2fccf4f026ef2a97d9e1e487ff1c2c127fed7cdc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 26 May 2019 16:05:12 +0200 Subject: [PATCH 45/69] mt76: mt7615: init get_txpower mac80211 callback Initialize get_txpower mac80211 callback to mt76_get_txpower in order to report the configured tx power to mac80211 Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 72bdb871ca138..cedc4c25f34d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -493,4 +493,5 @@ const struct ieee80211_ops mt7615_ops = { .sw_scan_start = mt7615_sw_scan, .sw_scan_complete = mt7615_sw_scan_complete, .release_buffered_frames = mt76_release_buffered_frames, + .get_txpower = mt76_get_txpower, }; From 892fe32b9c7a411eec68869aba428c19b1f4b9eb Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 26 May 2019 16:05:13 +0200 Subject: [PATCH 46/69] mt76: mt7615: rearrange locking in mt7615_config Since all the routines in mt7615_config grub mt76.mutex moves mutex_lock/mutex_unlock at the beginning/end of mt7615_config Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index cedc4c25f34d8..c8411750f62b2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -191,31 +191,28 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) struct mt7615_dev *dev = hw->priv; int ret = 0; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - mutex_lock(&dev->mt76.mutex); + mutex_lock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); ret = mt7615_set_channel(dev, &hw->conf.chandef); ieee80211_wake_queues(hw); - - mutex_unlock(&dev->mt76.mutex); } if (changed & IEEE80211_CONF_CHANGE_POWER) ret = mt7615_mcu_set_tx_power(dev); if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - mutex_lock(&dev->mt76.mutex); - if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; else dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); - - mutex_unlock(&dev->mt76.mutex); } + + mutex_unlock(&dev->mt76.mutex); + return ret; } From d2679d65fef6abb59f483166b4c9e3111da1d6e3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 29 May 2019 10:25:55 +0200 Subject: [PATCH 47/69] mt76: move mt76_get_rate in mt76-module Move mt7603_get_rate in mac80211.c and rename it to mt76_get_rate since it is shared between mt7603 and mt7615 drivers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 24 +++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++ .../net/wireless/mediatek/mt76/mt7603/mac.c | 30 ++----------------- .../net/wireless/mediatek/mt76/mt7615/mac.c | 30 ++----------------- 4 files changed, 33 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index f9e83971902ef..ec9efb79985fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -854,3 +854,27 @@ void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) status->flag &= ~RX_FLAG_IV_STRIPPED; } EXPORT_SYMBOL_GPL(mt76_insert_ccmp_hdr); + +int mt76_get_rate(struct mt76_dev *dev, + struct ieee80211_supported_band *sband, + int idx, bool cck) +{ + int i, offset = 0, len = sband->n_bitrates; + + if (cck) { + if (sband == &dev->sband_5g.sband) + return 0; + + idx &= ~BIT(2); /* short preamble */ + } else if (sband == &dev->sband_2g.sband) { + offset = 4; + } + + for (i = offset; i < len; i++) { + if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) + return i; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_get_rate); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index eef0e5aa6dd0c..00ae1d6838465 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -760,6 +760,9 @@ void mt76_csa_finish(struct mt76_dev *dev); int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id); +int mt76_get_rate(struct mt76_dev *dev, + struct ieee80211_supported_band *sband, + int idx, bool cck); /* internal */ void mt76_tx_free(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 5c09b2dbf3fda..2648fa333f93b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -370,31 +370,6 @@ void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val); } -static int -mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, - int idx, bool cck) -{ - int offset = 0; - int len = sband->n_bitrates; - int i; - - if (cck) { - if (sband == &dev->mt76.sband_5g.sband) - return 0; - - idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->mt76.sband_2g.sband) { - offset = 4; - } - - for (i = offset; i < len; i++) { - if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) - return i; - } - - return 0; -} - static struct mt76_wcid * mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) { @@ -508,7 +483,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - i = mt7603_get_rate(dev, sband, i, cck); + i = mt76_get_rate(&dev->mt76, sband, i, cck); break; case MT_PHY_TYPE_HT_GF: case MT_PHY_TYPE_HT: @@ -1018,7 +993,8 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, else sband = &dev->mt76.sband_2g.sband; final_rate &= GENMASK(5, 0); - final_rate = mt7603_get_rate(dev, sband, final_rate, cck); + final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, + cck); final_rate_flags = 0; break; case MT_PHY_TYPE_HT_GF: diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 1547bce561d38..7ca2e31f96fcc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -36,31 +36,6 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, return &sta->vif->sta.wcid; } -static int mt7615_get_rate(struct mt7615_dev *dev, - struct ieee80211_supported_band *sband, - int idx, bool cck) -{ - int offset = 0; - int len = sband->n_bitrates; - int i; - - if (cck) { - if (sband == &dev->mt76.sband_5g.sband) - return 0; - - idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->mt76.sband_2g.sband) { - offset = 4; - } - - for (i = offset; i < len; i++) { - if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) - return i; - } - - return 0; -} - int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -154,7 +129,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - i = mt7615_get_rate(dev, sband, i, cck); + i = mt76_get_rate(&dev->mt76, sband, i, cck); break; case MT_PHY_TYPE_HT_GF: case MT_PHY_TYPE_HT: @@ -608,7 +583,8 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, else sband = &dev->mt76.sband_2g.sband; final_rate &= MT_TX_RATE_IDX; - final_rate = mt7615_get_rate(dev, sband, final_rate, cck); + final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, + cck); final_rate_flags = 0; break; case MT_PHY_TYPE_HT_GF: From d3edd108e54e95e70ea8fc95d60d95bcebb1267d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 29 May 2019 22:53:56 +0800 Subject: [PATCH 48/69] mt76: Remove set but not used variables 'pid' and 'final_mpdu' Fixes gcc '-Wunused-but-set-variable' warnings: drivers/net/wireless/mediatek/mt76/mt7603/mac.c: In function mt7603_fill_txs: drivers/net/wireless/mediatek/mt76/mt7603/mac.c:969:5: warning: variable pid set but not used [-Wunused-but-set-variable] drivers/net/wireless/mediatek/mt76/mt7603/mac.c:961:7: warning: variable final_mpdu set but not used [-Wunused-but-set-variable] drivers/net/wireless/mediatek/mt76/mt7615/mac.c: In function mt7615_fill_txs: drivers/net/wireless/mediatek/mt76/mt7615/mac.c:555:5: warning: variable pid set but not used [-Wunused-but-set-variable] drivers/net/wireless/mediatek/mt76/mt7615/mac.c:552:19: warning: variable final_mpdu set but not used [-Wunused-but-set-variable] They are never used, so can be removed. Signed-off-by: YueHaibing Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 4 ---- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 2648fa333f93b..6629dd64cc223 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -909,7 +909,6 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, int final_idx = 0; u32 final_rate; u32 final_rate_flags; - bool final_mpdu; bool ack_timeout; bool fixed_rate; bool probe; @@ -917,7 +916,6 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, bool cck = false; int count; u32 txs; - u8 pid; int idx; int i; @@ -925,9 +923,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); txs = le32_to_cpu(txs_data[4]); - final_mpdu = txs & MT_TXS4_ACKED_MPDU; ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU); - pid = FIELD_GET(MT_TXS4_PID, txs); count = FIELD_GET(MT_TXS4_TX_COUNT, txs); txs = le32_to_cpu(txs_data[0]); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 7ca2e31f96fcc..b60d42b5923d5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -504,23 +504,20 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, { struct ieee80211_supported_band *sband; int i, idx, count, final_idx = 0; - bool fixed_rate, final_mpdu, ack_timeout; + bool fixed_rate, ack_timeout; bool probe, ampdu, cck = false; u32 final_rate, final_rate_flags, final_nss, txs; - u8 pid; fixed_rate = info->status.rates[0].count; probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); txs = le32_to_cpu(txs_data[1]); - final_mpdu = txs & MT_TXS1_ACKED_MPDU; ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU); txs = le32_to_cpu(txs_data[3]); count = FIELD_GET(MT_TXS3_TX_COUNT, txs); txs = le32_to_cpu(txs_data[0]); - pid = FIELD_GET(MT_TXS0_PID, txs); final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; From f4ec7fdf7f83701dd980d6cd60c81f79dab85133 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Mon, 3 Jun 2019 14:08:43 +0800 Subject: [PATCH 49/69] mt76: mt7615: enable support for mesh Enable NL80211_IFTYPE_MESH_POINT and update its path. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7615/main.c | 1 + drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt7615/mcu.h | 6 ------ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 369b9a8e07be8..a0e2b8770ad0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -133,6 +133,9 @@ static const struct ieee80211_iface_limit if_limits[] = { { .max = MT7615_MAX_INTERFACES, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_STATION) } }; @@ -195,6 +198,9 @@ int mt7615_register_device(struct mt7615_dev *dev) dev->mt76.antenna_mask = 0xf; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_AP); ret = mt76_register_device(&dev->mt76, true, mt7615_rates, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index c8411750f62b2..9a13e38ac2fe5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -37,6 +37,7 @@ static int get_omac_idx(enum nl80211_iftype type, u32 mask) switch (type) { case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: /* ap use hw bssid 0 and ext bssid */ if (~mask & BIT(HW_BSSID_0)) return HW_BSSID_0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 0e12e9f05f95c..b6273adbf0de7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -754,6 +754,7 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, switch (vif->type) { case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: tx_wlan_idx = mvif->sta.wcid.idx; conn_type = CONNECTION_INFRA_AP; break; @@ -968,7 +969,7 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, .rx_wtbl = { .tag = cpu_to_le16(WTBL_RX), .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = vif->type != NL80211_IFTYPE_AP, + .rca1 = vif->type == NL80211_IFTYPE_STATION, .rca2 = 1, .rv = 1, }, @@ -1042,6 +1043,7 @@ static void sta_rec_convert_vif_type(enum nl80211_iftype type, u32 *conn_type) { switch (type) { case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: if (conn_type) *conn_type = CONNECTION_INFRA_STA; break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index cca11737693c0..f8b51ad25220c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -106,25 +106,19 @@ enum { #define STA_TYPE_STA BIT(0) #define STA_TYPE_AP BIT(1) #define STA_TYPE_ADHOC BIT(2) -#define STA_TYPE_TDLS BIT(3) #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_MESH BIT(19) -#define NETWORK_BOW BIT(20) #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_MESH_STA (STA_TYPE_STA | NETWORK_MESH) -#define CONNECTION_MESH_AP (STA_TYPE_AP | NETWORK_MESH) #define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS) -#define CONNECTION_TDLS (STA_TYPE_STA | NETWORK_INFRA | STA_TYPE_TDLS) #define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS) #define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA) From fe559aedef0fc679fd9962afddcb02a375392191 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Mon, 3 Jun 2019 14:08:44 +0800 Subject: [PATCH 50/69] mt76: mt7615: fix slow performance when enable encryption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix wrong WCID assignment and add RKV (RX Key of this entry is valid) flag to check if peer uses the same configuration with previous handshaking. If the configuration is mismatch, WTBL indicates a “cipher mismatch” to stop SEC decryption to prevent the packet from damage. Suggested-by: YF Luo Suggested-by: Yiwei Chung Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 16 ++++++++++------ drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 1 + 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index a0e2b8770ad0f..693e597a3230f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -62,16 +62,11 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_AGG_ARCR_RATE_DOWN_RATIO_EN | FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); - - dev->mt76.global_wcid.idx = MT7615_WTBL_RESERVED; - dev->mt76.global_wcid.hw_key_idx = -1; - rcu_assign_pointer(dev->mt76.wcid[MT7615_WTBL_RESERVED], - &dev->mt76.global_wcid); } static int mt7615_init_hardware(struct mt7615_dev *dev) { - int ret; + int ret, idx; mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); @@ -98,6 +93,15 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) mt7615_mcu_ctrl_pm_state(dev, 0); mt7615_mcu_del_wtbl_all(dev); + /* Beacon and mgmt frames should occupy wcid 0 */ + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1); + if (idx) + return -ENOSPC; + + dev->mt76.global_wcid.idx = idx; + dev->mt76.global_wcid.hw_key_idx = -1; + rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 9a13e38ac2fe5..d21407ddda31e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -95,7 +95,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, dev->vif_mask |= BIT(mvif->idx); dev->omac_mask |= BIT(mvif->omac_idx); - idx = MT7615_WTBL_RESERVED - 1 - mvif->idx; + idx = MT7615_WTBL_RESERVED - mvif->idx; mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index b6273adbf0de7..3e0dc21997a60 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -882,6 +882,7 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, if (cipher == MT_CIPHER_NONE && key) return -EOPNOTSUPP; + req.key.rkv = 1; req.key.cipher_id = cipher; req.key.key_id = key->keyidx; req.key.key_len = key->keylen; From 80d2cb4e9c438d59eb2ce8b0451274b5959d63c0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 4 Jun 2019 12:06:06 +0200 Subject: [PATCH 51/69] mt76: mt7615: remove unused variable in mt7615_mcu_set_bcn Remove tim_len in mt7615_mcu_set_bcn since it is not actually used and ieee80211_beacon_get_tim checks if tim_length is NULL Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 3e0dc21997a60..f2f6b77666f82 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1129,10 +1129,10 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, /* pky_type: 0 for bcn, 1 for tim */ .pkt_type = 0, }; - u16 tim_off, tim_len; struct sk_buff *skb; + u16 tim_off; - skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, &tim_len); + skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, NULL); if (!skb) return -EINVAL; From f57d8fa7fbcc26831b9aea8501aff9986089665f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 5 Jun 2019 00:12:20 +0200 Subject: [PATCH 52/69] mt76: mt7615: remove key check in mt7615_mcu_set_wtbl_key Do not check key pointer in mt7615_mcu_set_wtbl_key since if set_key_cmd is SET_KEY, key will be always not NULL. This patch will address a false positive reported by Coverity-Scan Addresses-Coverity-ID: 1445463 ("Dereference after null check") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index f2f6b77666f82..76431d00a8ac0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -879,7 +879,7 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, u8 cipher; cipher = mt7615_get_key_info(key, req.key.key_material); - if (cipher == MT_CIPHER_NONE && key) + if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP; req.key.rkv = 1; From 10ece0086f33c3650df862869ab8ac015d6592b5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 25 Jun 2019 12:25:25 +0200 Subject: [PATCH 53/69] mt76: mt76x0: fix RF frontend initialization for external PA When loading EEPROM data from flash, the RF frontend settings need to be initialized from flash data. Without this, the chip loads the wrong values from its internal eFuse ROM. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 13 +++++++------ drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 3 +++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 1fd22eb841c38..610819b49bfc5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -430,15 +430,15 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u16 rf_bw_band) static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) { u16 ee_ant = mt76x02_eeprom_get(dev, MT_EE_ANTENNA); + u16 ee_cfg1 = mt76x02_eeprom_get(dev, MT_EE_CFG1_INIT); u16 nic_conf2 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2); - u32 wlan, coex3, cmb; + u32 wlan, coex3; bool ant_div; wlan = mt76_rr(dev, MT_WLAN_FUN_CTRL); - cmb = mt76_rr(dev, MT_CMB_CTRL); coex3 = mt76_rr(dev, MT_COEXCFG3); - cmb &= ~(BIT(14) | BIT(12)); + ee_ant &= ~(BIT(14) | BIT(12)); wlan &= ~(BIT(6) | BIT(5)); coex3 &= ~GENMASK(5, 2); @@ -447,7 +447,7 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) ant_div = !(nic_conf2 & MT_EE_NIC_CONF_2_ANT_OPT) && (nic_conf2 & MT_EE_NIC_CONF_2_ANT_DIV); if (ant_div) - cmb |= BIT(12); + ee_ant |= BIT(12); else coex3 |= BIT(4); coex3 |= BIT(3); @@ -464,10 +464,11 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) } if (is_mt7630(dev)) - cmb |= BIT(14) | BIT(11); + ee_ant |= BIT(14) | BIT(11); mt76_wr(dev, MT_WLAN_FUN_CTRL, wlan); - mt76_wr(dev, MT_CMB_CTRL, cmb); + mt76_rmw(dev, MT_CMB_CTRL, GENMASK(15, 0), ee_ant); + mt76_rmw(dev, MT_CSR_EE_CFG1, GENMASK(15, 0), ee_cfg1); mt76_clear(dev, MT_COEXCFG0, BIT(2)); mt76_wr(dev, MT_COEXCFG3, coex3); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h index e3442bc4e0a4f..0ba536de3d6e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h @@ -26,6 +26,7 @@ enum mt76x02_eeprom_field { MT_EE_MAC_ADDR = 0x004, MT_EE_PCI_ID = 0x00A, MT_EE_ANTENNA = 0x022, + MT_EE_CFG1_INIT = 0x024, MT_EE_NIC_CONF_0 = 0x034, MT_EE_NIC_CONF_1 = 0x036, MT_EE_COUNTRY_REGION_5GHZ = 0x038, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 2ce05b543dff1..ea7833964ec00 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -66,6 +66,9 @@ #define MT_WLAN_FUN_CTRL_GPIO_OUT GENMASK(23, 16) /* MT76x0 */ #define MT_WLAN_FUN_CTRL_GPIO_OUT_EN GENMASK(31, 24) /* MT76x0 */ +/* MT76x0 */ +#define MT_CSR_EE_CFG1 0x0104 + #define MT_XO_CTRL0 0x0100 #define MT_XO_CTRL1 0x0104 #define MT_XO_CTRL2 0x0108 From c5211e997eca0e3fc5c7c9e047ac6b073c3d74f4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 25 Jun 2019 00:03:45 +0200 Subject: [PATCH 54/69] mt76: mt7603: rework and fix tx status reporting Tx status reporting on mt7603 has a number of issues: - the hardware can alter the first rate index, but it is not reported to the driver - probing is very imprecise, because it alters the per-client rate set, but only considers info->status.rates for rate selection of a single probe packet - short/long GI selection has limitations, which are not accurately reported to mac80211 - if rates are changed while packets are in flight, tx status reports for the old rate set might be processed based on the new selection This led to very suboptimal rate selection with minstrel_ht. This patch completely reworks tx status reporting to get rid of these limitations: - Store the previous and current rate set in the driver + the TSF value at the time of the switch. - Use the tx status TSF value to determine which rate set needs to be used as reference. - Report only short or long GI rates for a single status event, not a mix. - The hardware reports the last used rate index. Use it along with the retry count to figure out what rate was used for the first attempt. - Use the same retry count value for all rate slots to make this calculation work. - Derive the probe rate from the current rateset instead of the skb cb - Do not wait for a status report for the probe frame before removing the probe rate from the rate table. Do it immediately after it was referenced in a tx status report. - Use the first half of the first rate retry budget for the probe rate in order to avoid using too many retries on that rate With this patch, throughput under bad link conditions is improved significantly, and there is a lot less rate fluctuation going on. Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7603/init.c | 5 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 127 +++++++++++++----- .../wireless/mediatek/mt76/mt7603/mt7603.h | 11 +- .../net/wireless/mediatek/mt76/mt7603/regs.h | 6 + 4 files changed, 108 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index f655091d106b4..ddf47c9eb67f9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -229,9 +229,8 @@ mt7603_mac_init(struct mt7603_dev *dev) mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7)); mt76_wr(dev, MT_AGG_ARDCR, - FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 0) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), - max_t(int, 0, MT7603_RATE_RETRY - 2)) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7603_RATE_RETRY - 1) | diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 6629dd64cc223..40db1cbc832d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -591,6 +591,7 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates) { + struct ieee80211_tx_rate *ref; int wcid = sta->wcid.idx; u32 addr = mt7603_wtbl2_addr(wcid); bool stbc = false; @@ -599,7 +600,8 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, u16 val[4]; u16 probe_val; u32 w9 = mt76_rr(dev, addr + 9 * 4); - int i; + bool rateset; + int i, k; if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) return; @@ -607,6 +609,41 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, for (i = n_rates; i < 4; i++) rates[i] = rates[n_rates - 1]; + rateset = !(sta->rate_set_tsf & BIT(0)); + memcpy(sta->rateset[rateset].rates, rates, + sizeof(sta->rateset[rateset].rates)); + if (probe_rate) { + sta->rateset[rateset].probe_rate = *probe_rate; + ref = &sta->rateset[rateset].probe_rate; + } else { + sta->rateset[rateset].probe_rate.idx = -1; + ref = &sta->rateset[rateset].rates[0]; + } + + rates = sta->rateset[rateset].rates; + for (i = 0; i < ARRAY_SIZE(sta->rateset[rateset].rates); i++) { + /* + * We don't support switching between short and long GI + * within the rate set. For accurate tx status reporting, we + * need to make sure that flags match. + * For improved performance, avoid duplicate entries by + * decrementing the MCS index if necessary + */ + if ((ref->flags ^ rates[i].flags) & IEEE80211_TX_RC_SHORT_GI) + rates[i].flags ^= IEEE80211_TX_RC_SHORT_GI; + + for (k = 0; k < i; k++) { + if (rates[i].idx != rates[k].idx) + continue; + if ((rates[i].flags ^ rates[k].flags) & + IEEE80211_TX_RC_40_MHZ_WIDTH) + continue; + + rates[i].idx--; + } + + } + w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | MT_WTBL2_W9_SHORT_GI_80; @@ -650,19 +687,22 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, mt76_wr(dev, MT_WTBL_RIUCR1, FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) | FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) | - FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0])); + FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[1])); mt76_wr(dev, MT_WTBL_RIUCR2, - FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[1] >> 8) | FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) | - FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[2]) | FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2])); mt76_wr(dev, MT_WTBL_RIUCR3, FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) | - FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) | + FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[3]) | FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3])); + mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + sta->rate_set_tsf = (mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0)) | rateset; + mt76_wr(dev, MT_WTBL_UPDATE, FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) | MT_WTBL_UPDATE_RATE_UPDATE | @@ -889,9 +929,9 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { spin_lock_bh(&dev->mt76.lock); - msta->rate_probe = true; mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0], msta->rates); + msta->rate_probe = true; spin_unlock_bh(&dev->mt76.lock); } @@ -906,9 +946,12 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, struct ieee80211_tx_info *info, __le32 *txs_data) { struct ieee80211_supported_band *sband; - int final_idx = 0; + struct mt7603_rate_set *rs; + int first_idx = 0, last_idx; + u32 rate_set_tsf; u32 final_rate; u32 final_rate_flags; + bool rs_idx; bool ack_timeout; bool fixed_rate; bool probe; @@ -925,6 +968,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, txs = le32_to_cpu(txs_data[4]); ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU); count = FIELD_GET(MT_TXS4_TX_COUNT, txs); + last_idx = FIELD_GET(MT_TXS4_LAST_TX_RATE, txs); txs = le32_to_cpu(txs_data[0]); final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); @@ -946,38 +990,57 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU)) info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU; + first_idx = max_t(int, 0, last_idx - (count + 1) / MT7603_RATE_RETRY); + if (fixed_rate && !probe) { info->status.rates[0].count = count; + i = 0; goto out; } - for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) { - int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY); + rate_set_tsf = READ_ONCE(sta->rate_set_tsf); + rs_idx = !((u32)(FIELD_GET(MT_TXS1_F0_TIMESTAMP, le32_to_cpu(txs_data[1])) - + rate_set_tsf) < 1000000); + rs_idx ^= rate_set_tsf & BIT(0); + rs = &sta->rateset[rs_idx]; - if (!i && probe) { - cur_count = 1; - } else { - info->status.rates[i] = sta->rates[idx]; - idx++; - } + if (!first_idx && rs->probe_rate.idx >= 0) { + info->status.rates[0] = rs->probe_rate; - if (i && info->status.rates[i].idx < 0) { - info->status.rates[i - 1].count += count; - break; + spin_lock_bh(&dev->mt76.lock); + if (sta->rate_probe) { + mt7603_wtbl_set_rates(dev, sta, NULL, + sta->rates); + sta->rate_probe = false; } + spin_unlock_bh(&dev->mt76.lock); + } else + info->status.rates[0] = rs->rates[first_idx / 2]; + info->status.rates[0].count = 0; - if (!count) { - info->status.rates[i].idx = -1; - break; - } + for (i = 0, idx = first_idx; count && idx <= last_idx; idx++) { + struct ieee80211_tx_rate *cur_rate; + int cur_count; - info->status.rates[i].count = cur_count; - final_idx = i; + cur_rate = &rs->rates[idx / 2]; + cur_count = min_t(int, MT7603_RATE_RETRY, count); count -= cur_count; + + if (idx && (cur_rate->idx != info->status.rates[i].idx || + cur_rate->flags != info->status.rates[i].flags)) { + i++; + if (i == ARRAY_SIZE(info->status.rates)) + break; + + info->status.rates[i] = *cur_rate; + info->status.rates[i].count = 0; + } + + info->status.rates[i].count += cur_count; } out: - final_rate_flags = info->status.rates[final_idx].flags; + final_rate_flags = info->status.rates[i].flags; switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) { case MT_PHY_TYPE_CCK: @@ -1004,8 +1067,8 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, return false; } - info->status.rates[final_idx].idx = final_rate; - info->status.rates[final_idx].flags = final_rate_flags; + info->status.rates[i].idx = final_rate; + info->status.rates[i].flags = final_rate_flags; return true; } @@ -1026,16 +1089,6 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, if (skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { - spin_lock_bh(&dev->mt76.lock); - if (sta->rate_probe) { - mt7603_wtbl_set_rates(dev, sta, NULL, - sta->rates); - sta->rate_probe = false; - } - spin_unlock_bh(&dev->mt76.lock); - } - if (!mt7603_fill_txs(dev, sta, info, txs_data)) { ieee80211_tx_info_clear_status(info); info->status.rates[0].idx = -1; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 944dc9a11a153..60f8269daae7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -51,6 +51,11 @@ enum mt7603_bw { MT_BW_80, }; +struct mt7603_rate_set { + struct ieee80211_tx_rate probe_rate; + struct ieee80211_tx_rate rates[4]; +}; + struct mt7603_sta { struct mt76_wcid wcid; /* must be first */ @@ -58,7 +63,11 @@ struct mt7603_sta { struct sk_buff_head psq; - struct ieee80211_tx_rate rates[8]; + struct ieee80211_tx_rate rates[4]; + + struct mt7603_rate_set rateset[2]; + u32 rate_set_tsf; + u8 rate_count; u8 n_rates; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 9d257d5c309d1..eb9eefe8e1251 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -480,6 +480,12 @@ enum { #define MT_LPON_BASE 0x24000 #define MT_LPON(n) (MT_LPON_BASE + (n)) +#define MT_LPON_T0CR MT_LPON(0x010) +#define MT_LPON_T0CR_MODE GENMASK(1, 0) + +#define MT_LPON_UTTR0 MT_LPON(0x018) +#define MT_LPON_UTTR1 MT_LPON(0x01c) + #define MT_LPON_BTEIR MT_LPON(0x020) #define MT_LPON_BTEIR_MBSS_MODE GENMASK(31, 29) From ac7ff57127cc5aec434b2220f6e80ab319646984 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 25 Jun 2019 00:16:20 +0200 Subject: [PATCH 55/69] mt76: mt7603: improve hardware rate switching configuration Now that tx status reporting can figure out the first attempted rate, we can make switching from lower rates to higher rates more conservative. This reduces retries under bad link conditions and ensures that fallback rates get more test coverage Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/init.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index ddf47c9eb67f9..85744cdd09f81 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -227,7 +227,16 @@ mt7603_mac_init(struct mt7603_dev *dev) mt76_rmw_field(dev, MT_LPON_BTEIR, MT_LPON_BTEIR_MBSS_MODE, 2); mt76_rmw_field(dev, MT_WF_RMACDR, MT_WF_RMACDR_MBSSID_MASK, 2); - mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7)); + mt76_wr(dev, MT_AGG_ARUCR, + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); + mt76_wr(dev, MT_AGG_ARDCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7603_RATE_RETRY - 1) | From 760556042acdd4f0c964fd6403f828b33fce3822 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 8 Jun 2019 16:44:36 +0200 Subject: [PATCH 56/69] mt76: mt7615: simplify mt7615_mcu_set_sta_rec routine Move conn_type configuration directly in mt7615_mcu_set_sta_rec and remove sta_rec_convert_vif_type since it is actually used just in mt7615_mcu_set_sta_rec Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 76431d00a8ac0..79baa455034cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1040,30 +1040,11 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, &req, sizeof(req), true); } -static void sta_rec_convert_vif_type(enum nl80211_iftype type, u32 *conn_type) -{ - switch (type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - if (conn_type) - *conn_type = CONNECTION_INFRA_STA; - break; - case NL80211_IFTYPE_STATION: - if (conn_type) - *conn_type = CONNECTION_INFRA_AP; - break; - default: - WARN_ON(1); - break; - }; -} - int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - u32 conn_type = 0; struct { struct sta_req_hdr hdr; @@ -1085,8 +1066,18 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, }; memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); - sta_rec_convert_vif_type(vif->type, &conn_type); - req.basic.conn_type = cpu_to_le32(conn_type); + switch (vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); + break; + case NL80211_IFTYPE_STATION: + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); + break; + default: + WARN_ON(1); + break; + }; if (en) { req.basic.conn_state = CONN_STATE_PORT_SECURE; From bf92e76851009e6bf082db9e9de9b0ab9320cf26 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 13 Jun 2019 15:13:29 +0800 Subject: [PATCH 57/69] mt76: mt7615: add support for per-chain signal strength reporting Fill in RX status->chain_signal to avoid empty value. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mac.c | 22 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7615/mac.h | 5 +++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index b60d42b5923d5..1eb0e9c9970ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -13,6 +13,11 @@ #include "../dma.h" #include "mac.h" +static inline s8 to_rssi(u32 field, u32 rxv) +{ + return (FIELD_GET(field, rxv) - 220) / 2; +} + static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) { @@ -120,6 +125,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { u32 rxdg0 = le32_to_cpu(rxd[0]); u32 rxdg1 = le32_to_cpu(rxd[1]); + u32 rxdg3 = le32_to_cpu(rxd[3]); u8 stbc = FIELD_GET(MT_RXV1_HT_STBC, rxdg0); bool cck = false; @@ -169,7 +175,21 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - /* TODO: RSSI */ + status->chains = dev->mt76.antenna_mask; + status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3); + status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); + status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); + status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); + status->signal = status->chain_signal[0]; + + for (i = 1; i < hweight8(dev->mt76.antenna_mask); i++) { + if (!(status->chains & BIT(i))) + continue; + + status->signal = max(status->signal, + status->chain_signal[i]); + } + rxd += 6; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 18ad4b8a3807c..b00ce8db58e94 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -98,6 +98,11 @@ enum rx_pkt_type { #define MT_RXV2_GROUP_ID GENMASK(26, 21) #define MT_RXV2_LENGTH GENMASK(20, 0) +#define MT_RXV4_RCPI3 GENMASK(31, 24) +#define MT_RXV4_RCPI2 GENMASK(23, 16) +#define MT_RXV4_RCPI1 GENMASK(15, 8) +#define MT_RXV4_RCPI0 GENMASK(7, 0) + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, From 391ff7ffd149da87019d652cd678d9e76103e415 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 11 Jun 2019 08:38:52 +0200 Subject: [PATCH 58/69] mt76: mt7615: init per-channel target power Set per-channel target power as the minimum between the regulatory tx power and the value configured in the eeprom Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 693e597a3230f..3f826e4f1cd6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -165,6 +165,46 @@ static int mt7615_init_debugfs(struct mt7615_dev *dev) return 0; } +static void +mt7615_init_txpower(struct mt7615_dev *dev, + struct ieee80211_supported_band *sband) +{ + int i, n_chains = hweight8(dev->mt76.antenna_mask); + u8 *eep = (u8 *)dev->mt76.eeprom.data; + + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *chan = &sband->channels[i]; + u8 target_power = 0; + int j; + + for (j = 0; j < n_chains; j++) { + int index; + + index = mt7615_eeprom_get_power_index(chan, j); + target_power = max(target_power, eep[index]); + } + + target_power = DIV_ROUND_UP(target_power, 2); + switch (n_chains) { + case 4: + target_power += 6; + break; + case 3: + target_power += 4; + break; + case 2: + target_power += 3; + break; + default: + break; + } + + chan->max_power = min_t(int, chan->max_reg_power, + target_power); + chan->orig_mpwr = target_power; + } +} + int mt7615_register_device(struct mt7615_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); @@ -212,6 +252,9 @@ int mt7615_register_device(struct mt7615_dev *dev) if (ret) return ret; + mt7615_init_txpower(dev, &dev->mt76.sband_2g.sband); + mt7615_init_txpower(dev, &dev->mt76.sband_5g.sband); + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; return mt7615_init_debugfs(dev); From 16a2f8e2cad50618f7c5ccf18e83263f940afdb0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 11 Jun 2019 08:38:53 +0200 Subject: [PATCH 59/69] mt76: mt7615: take into account extPA when configuring tx power When TSSI calibration is disabled (which it means the device has been equipped with an external power amplifier) we need to refer to different eeprom fields in order to properly configure tx power Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/eeprom.c | 12 +++++++++++- .../net/wireless/mediatek/mt76/mt7615/eeprom.h | 17 +++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/init.c | 9 ++++++--- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 10 ++++++---- .../net/wireless/mediatek/mt76/mt7615/mt7615.h | 3 ++- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 023c8bbc767dd..dc94f52e6e8b9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -110,7 +110,8 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) } } -int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan, +int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, + struct ieee80211_channel *chan, u8 chain_idx) { int index; @@ -118,6 +119,15 @@ int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan, if (chain_idx > 3) return -EINVAL; + /* TSSI disabled */ + if (mt7615_ext_pa_enabled(dev, chan->band)) { + if (chan->band == NL80211_BAND_2GHZ) + return MT_EE_EXT_PA_2G_TARGET_POWER; + else + return MT_EE_EXT_PA_5G_TARGET_POWER; + } + + /* TSSI enabled */ if (chan->band == NL80211_BAND_2GHZ) { index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6; } else { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index 3c9086b67f515..f4a4280768d21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -11,16 +11,22 @@ enum mt7615_eeprom_field { MT_EE_VERSION = 0x002, MT_EE_MAC_ADDR = 0x004, MT_EE_NIC_CONF_0 = 0x034, + MT_EE_NIC_CONF_1 = 0x036, MT_EE_WIFI_CONF = 0x03e, MT_EE_TX0_2G_TARGET_POWER = 0x058, MT_EE_TX0_5G_G0_TARGET_POWER = 0x070, MT_EE_TX1_5G_G0_TARGET_POWER = 0x098, + MT_EE_EXT_PA_2G_TARGET_POWER = 0x0f2, + MT_EE_EXT_PA_5G_TARGET_POWER = 0x0f3, MT_EE_TX2_5G_G0_TARGET_POWER = 0x142, MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a, __MT_EE_MAX = 0x3bf }; +#define MT_EE_NIC_CONF_TSSI_2G BIT(5) +#define MT_EE_NIC_CONF_TSSI_5G BIT(6) + #define MT_EE_NIC_WIFI_CONF_BAND_SEL GENMASK(5, 4) enum mt7615_eeprom_band { MT_EE_DUAL_BAND, @@ -59,4 +65,15 @@ mt7615_get_channel_group(int channel) return MT_CH_5G_UNII_3; } +static inline bool +mt7615_ext_pa_enabled(struct mt7615_dev *dev, enum nl80211_band band) +{ + u8 *eep = dev->mt76.eeprom.data; + + if (band == NL80211_BAND_5GHZ) + return !(eep[MT_EE_NIC_CONF_1 + 1] & MT_EE_NIC_CONF_TSSI_5G); + else + return !(eep[MT_EE_NIC_CONF_1 + 1] & MT_EE_NIC_CONF_TSSI_2G); +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 3f826e4f1cd6d..859de2454ec68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -9,6 +9,7 @@ #include #include "mt7615.h" #include "mac.h" +#include "eeprom.h" static void mt7615_phy_init(struct mt7615_dev *dev) { @@ -169,18 +170,20 @@ static void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband) { - int i, n_chains = hweight8(dev->mt76.antenna_mask); + int i, n_chains = hweight8(dev->mt76.antenna_mask), target_chains; u8 *eep = (u8 *)dev->mt76.eeprom.data; + enum nl80211_band band = sband->band; + target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; for (i = 0; i < sband->n_channels; i++) { struct ieee80211_channel *chan = &sband->channels[i]; u8 target_power = 0; int j; - for (j = 0; j < n_chains; j++) { + for (j = 0; j < target_chains; j++) { int index; - index = mt7615_eeprom_get_power_index(chan, j); + index = mt7615_eeprom_get_power_index(dev, chan, j); target_power = max(target_power, eep[index]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 79baa455034cd..f3dd76f88ff14 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1149,9 +1149,10 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) { int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + int freq = chandef->center_freq1, len, target_chains; u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; + enum nl80211_band band = chandef->chan->band; struct ieee80211_hw *hw = mt76_hw(dev); - int freq = chandef->center_freq1, len; struct { u8 center_chan; u8 dbdc_idx; @@ -1159,7 +1160,7 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) u8 rsv; } __packed req_hdr = { .center_chan = ieee80211_frequency_to_channel(freq), - .band = chandef->chan->band, + .band = band, }; s8 tx_power; @@ -1190,10 +1191,11 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) tx_power = max_t(s8, tx_power, 0); dev->mt76.txpower_cur = tx_power; - for (i = 0; i < n_chains; i++) { + target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; + for (i = 0; i < target_chains; i++) { int index = -MT_EE_NIC_CONF_0; - ret = mt7615_eeprom_get_power_index(chandef->chan, i); + ret = mt7615_eeprom_get_power_index(dev, chandef->chan, i); if (ret < 0) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 7c08d3b93a2a8..f02ffcffe6376 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -105,7 +105,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); -int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan, +int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, + struct ieee80211_channel *chan, u8 chain_idx); int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); From 18bb262787592d40c6c8d0ec4b505f19c69ea0e1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 12 Jun 2019 11:31:15 +0200 Subject: [PATCH 60/69] mt76: mt76x02u: fix sparse warnings: should it be static? Fix following sparse warnings in mt76x02_usb_core.c drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:29:6: warning: symbol 'mt76x02u_tx_complete_skb' was not declared. Should it be static? drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:37:5: warning: symbol 'mt76x02u_skb_dma_info' was not declared. Should it be static? drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:96:52: warning: restricted __le16 degrades to integer drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:74:5: warning: symbol 'mt76x02u_tx_prepare_skb' was not declared. Should it be static? drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:244:6: warning: symbol 'mt76x02u_init_beacon_config' was not declared. Should it be static? drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:262:6: warning: symbol 'mt76x02u_exit_beacon_config' was not declared. Should it be static? Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 42ec02b6cdd6c..5e4f3a8c57845 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "mt76x02.h" +#include "mt76x02_usb.h" static void mt76x02u_remove_dma_hdr(struct sk_buff *skb) { From 1a09d9e0e5f0e65fa3b5fc4df4e97651f0b544ef Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 13 Jun 2019 15:13:30 +0800 Subject: [PATCH 61/69] mt76: mt7615: fix incorrect settings in mesh mode Fix wrong settings that will drop packets due to hardware's RX table searching flow. Fixes: f072c7ba2150 ("mt76: mt7615: enable support for mesh") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index f3dd76f88ff14..90a62112f5ab1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -970,7 +970,7 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, .rx_wtbl = { .tag = cpu_to_le16(WTBL_RX), .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = vif->type == NL80211_IFTYPE_STATION, + .rca1 = vif->type != NL80211_IFTYPE_AP, .rca2 = 1, .rv = 1, }, From e991c4c2998353212adb1c2b7c3052d61fa6c307 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 13 Jun 2019 15:13:31 +0800 Subject: [PATCH 62/69] mt76: mt7615: update peer's bssid when state transition occurs This makes sure that the driver update peer's bssid when state transition occurs. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 5 ++-- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index d21407ddda31e..e0824392c019f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -283,9 +283,8 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&dev->mt76.mutex); - /* TODO: sta mode connect/disconnect - * BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID - */ + if (changed & BSS_CHANGED_ASSOC) + mt7615_mcu_set_bss_info(dev, vif, info->assoc); /* TODO: update beacon content * BSS_CHANGED_BEACON diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 90a62112f5ab1..836a329e65ab1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -759,22 +759,23 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, conn_type = CONNECTION_INFRA_AP; break; case NL80211_IFTYPE_STATION: { - struct ieee80211_sta *sta; - struct mt7615_sta *msta; - - rcu_read_lock(); - - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!sta) { + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ + if (en) { + struct ieee80211_sta *sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)sta->drv_priv; + tx_wlan_idx = msta->wcid.idx; rcu_read_unlock(); - return -EINVAL; } - - msta = (struct mt7615_sta *)sta->drv_priv; - tx_wlan_idx = msta->wcid.idx; conn_type = CONNECTION_INFRA_STA; - - rcu_read_unlock(); break; } default: From 14663f0c8d3df5119a3fc4a0e044836c6d3ab8d6 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 20 Jun 2019 12:39:36 +0200 Subject: [PATCH 63/69] mt76: mt76u: reduce rx memory footprint Reduce rx memory footprint allocating just one SG buffer since for the moment we support just 3839B as maximal size of an A-MSDU. Introduce different SG_MAX_SIZE definitions for TX and RX sides. Moreover set q->buf_size to PAGE_SIZE even for SG case. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 18 +++++++++++------- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 00ae1d6838465..e10ecbbb6ecf5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -382,7 +382,8 @@ enum mt76u_out_ep { __MT_EP_OUT_MAX, }; -#define MT_SG_MAX_SIZE 8 +#define MT_TX_SG_MAX_SIZE 8 +#define MT_RX_SG_MAX_SIZE 1 #define MT_NUM_TX_ENTRIES 256 #define MT_NUM_RX_ENTRIES 128 #define MCU_RESP_URB_SIZE 1024 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 7c38ec4418db2..5b9701ce6f370 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -191,7 +191,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) /* check hw sg support in order to enable AMSDU */ if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_SG_MAX_SIZE; + hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index f2c57d5b87f93..94f52f98019bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -225,7 +225,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) /* check hw sg support in order to enable AMSDU */ if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_SG_MAX_SIZE; + hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index bbaa1365bbda2..5a501e5a9fd46 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -333,12 +333,13 @@ mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp) } static int -mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, + int sg_max_size) { unsigned int size = sizeof(struct urb); if (dev->usb.sg_en) - size += MT_SG_MAX_SIZE * sizeof(struct scatterlist); + size += sg_max_size * sizeof(struct scatterlist); e->urb = kzalloc(size, GFP_KERNEL); if (!e->urb) @@ -357,11 +358,12 @@ mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) { int err; - err = mt76u_urb_alloc(dev, e); + err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); if (err) return err; - return mt76u_refill_rx(dev, e->urb, MT_SG_MAX_SIZE, GFP_KERNEL); + return mt76u_refill_rx(dev, e->urb, MT_RX_SG_MAX_SIZE, + GFP_KERNEL); } static void mt76u_urb_free(struct urb *urb) @@ -577,8 +579,9 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!q->entry) return -ENOMEM; - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; + q->buf_size = PAGE_SIZE; + for (i = 0; i < q->ndesc; i++) { err = mt76u_rx_urb_alloc(dev, &q->entry[i]); if (err < 0) @@ -735,7 +738,7 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, urb->transfer_buffer = skb->data; return 0; } else { - sg_init_table(urb->sg, MT_SG_MAX_SIZE); + sg_init_table(urb->sg, MT_TX_SG_MAX_SIZE); urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); if (urb->num_sgs == 0) return -ENOMEM; @@ -829,7 +832,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) q->ndesc = MT_NUM_TX_ENTRIES; for (j = 0; j < q->ndesc; j++) { - err = mt76u_urb_alloc(dev, &q->entry[j]); + err = mt76u_urb_alloc(dev, &q->entry[j], + MT_TX_SG_MAX_SIZE); if (err < 0) return err; } From 07d557f640ced1935f693903a2f31d123d403998 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 21 Jun 2019 19:15:26 +0200 Subject: [PATCH 64/69] mt76: mt7615: remove cfg80211_chan_def from mt7615_set_channel signature Simplify mt7615_set_channel signature removing cfg80211_chan_def parameter since it is not actually used Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index e0824392c019f..b4d6af812c548 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -130,8 +130,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); } -static int mt7615_set_channel(struct mt7615_dev *dev, - struct cfg80211_chan_def *def) +static int mt7615_set_channel(struct mt7615_dev *dev) { int ret; @@ -196,7 +195,7 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); - ret = mt7615_set_channel(dev, &hw->conf.chandef); + ret = mt7615_set_channel(dev); ieee80211_wake_queues(hw); } From d8b8890d5943ff68470c5a246fc500a830372812 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 21 Jun 2019 22:31:28 +0200 Subject: [PATCH 65/69] mt76: move nl80211_dfs_regions in mt76_dev data structure Move dfs region field in mt76_dev data structure since it is used by all drivers. This is a preliminary patch to add DFS support to mt7615 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ .../net/wireless/mediatek/mt76/mt7603/debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7603/init.c | 4 ++-- .../net/wireless/mediatek/mt76/mt7603/mt7603.h | 2 -- .../net/wireless/mediatek/mt76/mt76x02_debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | 16 ++++++++-------- drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h | 2 -- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e10ecbbb6ecf5..850ef1627b044 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -486,6 +486,8 @@ struct mt76_dev { int txpower_conf; int txpower_cur; + enum nl80211_dfs_regions region; + u32 debugfs_reg; struct led_classdev led_cdev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c index 9c0bea489e1fc..a1bc3103cbe94 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c @@ -49,7 +49,7 @@ mt7603_edcca_set(void *data, u64 val) dev->ed_monitor_enabled = !!val; dev->ed_monitor = dev->ed_monitor_enabled && - dev->region == NL80211_DFS_ETSI; + dev->mt76.region == NL80211_DFS_ETSI; mt7603_init_edcca(dev); mutex_unlock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 85744cdd09f81..38834c7d08918 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -445,9 +445,9 @@ mt7603_regd_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7603_dev *dev = hw->priv; - dev->region = request->dfs_region; + dev->mt76.region = request->dfs_region; dev->ed_monitor = dev->ed_monitor_enabled && - dev->region == NL80211_DFS_ETSI; + dev->mt76.region == NL80211_DFS_ETSI; } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 60f8269daae7c..2c6f7b4cf0e9f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -127,8 +127,6 @@ struct mt7603_dev { u8 mcu_running; - enum nl80211_dfs_regions region; - u8 ed_monitor_enabled; u8 ed_monitor; s8 ed_trigger; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index ffdba5ffc22df..1b1e424ccbb28 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -120,7 +120,7 @@ static int mt76_edcca_set(void *data, u64 val) { struct mt76x02_dev *dev = data; - enum nl80211_dfs_regions region = dev->dfs_pd.region; + enum nl80211_dfs_regions region = dev->mt76.region; mutex_lock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 84b8456478813..50e9b310e4966 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -283,7 +283,7 @@ static bool mt76x02_dfs_check_hw_pulse(struct mt76x02_dev *dev, if (!pulse->period || !pulse->w1) return false; - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: if (pulse->engine > 3) break; @@ -457,7 +457,7 @@ static int mt76x02_dfs_create_sequence(struct mt76x02_dev *dev, with_sum = event->width + cur_event->width; sw_params = &dfs_pd->sw_dpd_params; - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: case NL80211_DFS_JP: if (with_sum < 600) @@ -685,7 +685,7 @@ static void mt76x02_dfs_init_sw_detector(struct mt76x02_dev *dev) { struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: dfs_pd->sw_dpd_params.max_pri = MT_DFS_FCC_MAX_PRI; dfs_pd->sw_dpd_params.min_pri = MT_DFS_FCC_MIN_PRI; @@ -725,7 +725,7 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) break; } - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: radar_specs = &fcc_radar_specs[shift]; break; @@ -836,7 +836,7 @@ void mt76x02_dfs_init_params(struct mt76x02_dev *dev) struct cfg80211_chan_def *chandef = &dev->mt76.chandef; if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - dev->dfs_pd.region != NL80211_DFS_UNSET) { + dev->mt76.region != NL80211_DFS_UNSET) { mt76x02_dfs_init_sw_detector(dev); mt76x02_dfs_set_bbp_params(dev); /* enable debug mode */ @@ -869,7 +869,7 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev) INIT_LIST_HEAD(&dfs_pd->sequences); INIT_LIST_HEAD(&dfs_pd->seq_pool); - dfs_pd->region = NL80211_DFS_UNSET; + dev->mt76.region = NL80211_DFS_UNSET; dfs_pd->last_sw_check = jiffies; tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet, (unsigned long)dev); @@ -882,14 +882,14 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; mutex_lock(&dev->mt76.mutex); - if (dfs_pd->region != region) { + if (dev->mt76.region != region) { tasklet_disable(&dfs_pd->dfs_tasklet); dev->ed_monitor = dev->ed_monitor_enabled && region == NL80211_DFS_ETSI; mt76x02_edcca_init(dev); - dfs_pd->region = region; + dev->mt76.region = region; mt76x02_dfs_init_params(dev); tasklet_enable(&dfs_pd->dfs_tasklet); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h index 70b394e173403..0408613b45a43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h @@ -118,8 +118,6 @@ struct mt76x02_dfs_seq_stats { }; struct mt76x02_dfs_pattern_detector { - enum nl80211_dfs_regions region; - u8 chirp_pulse_cnt; u32 chirp_pulse_ts; From 81ca02a17404755f4baed82be1fce4604a25848e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 23 Jun 2019 22:25:39 +0200 Subject: [PATCH 66/69] mt76: mt76u: get rid of {out,in}_max_packet Remove {out,in}_max_packet from mt76_usb data structure since they just track last usb endpoint and they are not actually used Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 -- drivers/net/wireless/mediatek/mt76/usb.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 850ef1627b044..56bf93a8988e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -395,9 +395,7 @@ struct mt76_usb { struct delayed_work stat_work; u8 out_ep[__MT_EP_OUT_MAX]; - u16 out_max_packet; u8 in_ep[__MT_EP_IN_MAX]; - u16 in_max_packet; bool sg_en; struct mt76u_mcu { diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 5a501e5a9fd46..61b27f3ec6e47 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -267,12 +267,10 @@ mt76u_set_endpoints(struct usb_interface *intf, if (usb_endpoint_is_bulk_in(ep_desc) && in_ep < __MT_EP_IN_MAX) { usb->in_ep[in_ep] = usb_endpoint_num(ep_desc); - usb->in_max_packet = usb_endpoint_maxp(ep_desc); in_ep++; } else if (usb_endpoint_is_bulk_out(ep_desc) && out_ep < __MT_EP_OUT_MAX) { usb->out_ep[out_ep] = usb_endpoint_num(ep_desc); - usb->out_max_packet = usb_endpoint_maxp(ep_desc); out_ep++; } } From eda96044de274cbf7263834b5cecb51f1f7b0984 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 27 Jun 2019 10:44:49 +0200 Subject: [PATCH 67/69] mt76: mt7615: fix sparse warnings: incorrect type in assignment (different base types) Fix the following sparse warning in mt7615_mcu_bss_info_ext_header: drivers/net/wireless/mediatek/mt76/mt7615/mcu.c:728:30: sparse: sparse: incorrect type in assignment (different base types) drivers/net/wireless/mediatek/mt76/mt7615/mcu.c:728:30: sparse: expected restricted __le32 [usertype] mbss_tsf_offset Reported-by: kbuild test robot Fixes: 04b8e65922f6 ("mt76: add mac80211 driver for MT7615 PCIe-based chipsets") Fixes: 7339fbc0caa5 ("mt7615: mcu: do not use function pointers whenever possible") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 836a329e65ab1..8d01ee5df9a3e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -713,7 +713,7 @@ mt7615_mcu_bss_info_ext_header(struct mt7615_vif *mvif, u8 *data) /* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ #define BCN_TX_ESTIMATE_TIME (4096 + 20) struct bss_info_ext_bss *hdr = (struct bss_info_ext_bss *)data; - int ext_bss_idx; + int ext_bss_idx, tsf_offset; ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; if (ext_bss_idx < 0) @@ -721,7 +721,8 @@ mt7615_mcu_bss_info_ext_header(struct mt7615_vif *mvif, u8 *data) hdr->tag = cpu_to_le16(BSS_INFO_EXT_BSS); hdr->len = cpu_to_le16(sizeof(struct bss_info_ext_bss)); - hdr->mbss_tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + hdr->mbss_tsf_offset = cpu_to_le32(tsf_offset); } int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, From d923cf6bc38a7b174e6b813d1bf72c926539858c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 27 Jun 2019 11:50:25 +0200 Subject: [PATCH 68/69] mt76: mt7615: fix sparse warnings: warning: cast from restricted __le16 Do not convert {tx,rx}_mcs_map to little-endian since it is already done by mac80211. This patch fix the following sparse warning: drivers/net/wireless/mediatek/mt76/mt7615/mcu.c:1497:25: sparse: warning: cast from restricted __le16 drivers/net/wireless/mediatek/mt76/mt7615/mcu.c:1499:25: sparse: warning: cast from restricted __le16 Fixes: 04b8e65922f6 ("mt76: add mac80211 driver for MT7615 PCIe-based chipsets") Fixes: 3ca0a6f6e9df ("mt7615: mcu: use standard signature for mt7615_mcu_msg_send") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 8d01ee5df9a3e..cdad2c8dc2971 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1393,10 +1393,8 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, sta_vht->tag = cpu_to_le16(STA_REC_VHT); sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_vht->vht_rx_mcs_map = - cpu_to_le16(sta->vht_cap.vht_mcs.rx_mcs_map); - sta_vht->vht_tx_mcs_map = - cpu_to_le16(sta->vht_cap.vht_mcs.tx_mcs_map); + sta_vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + sta_vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; } ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, From 676fabd1d2f089f9fb8bece3476c2ab5584b4a1a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 27 Jun 2019 12:13:16 +0200 Subject: [PATCH 69/69] mt76: mt7603: fix sparse warnings: warning: incorrect type in assignment (different base types) Fix the following sparse warning in mt7603_mcu_set_eeprom: drivers/net/wireless/mediatek/mt76/mt7603/mcu.c:376:30: sparse: warning: incorrect type in assignment (different base types) drivers/net/wireless/mediatek/mt76/mt7603/mcu.c:376:30: sparse: expected unsigned short [usertype] addr drivers/net/wireless/mediatek/mt76/mt7603/mcu.c:376:30: sparse: got restricted __le16 [usertype] Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 6357b5658a32e..343ddc5543c27 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -346,7 +346,7 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) }; struct req_data { - u16 addr; + __le16 addr; u8 val; u8 pad; } __packed;