Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'mt76-next-2025-11-24' of https://github.com/nbd168/wireless

Felix Fietkau says:
===================
mt76 patches for 6.19

- relicense to BSD-3-Clause-Clear
- fixes
- support WED on devices which exceed 32-bit DMA
- airoha NPU support
- mt7925 regd improvements
- more mt7996 MLO work
===================

Link: https://patch.msgid.link/6b6d1033-dddf-4cc9-b240-93da7f8b8773@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+2504 -683
+66
Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
··· 151 151 - ETSI 152 152 - JP 153 153 154 + country: 155 + $ref: /schemas/types.yaml#/definitions/string 156 + pattern: '^[A-Z]{2}$' 157 + description: 158 + ISO 3166-1 alpha-2 country code for power limits 159 + 154 160 patternProperties: 155 161 "^txpower-[256]g$": 156 162 type: object ··· 215 209 items: 216 210 minItems: 13 217 211 maxItems: 13 212 + 213 + paths-cck: 214 + $ref: /schemas/types.yaml#/definitions/uint8-array 215 + minItems: 4 216 + maxItems: 4 217 + description: 218 + 4 half-dBm backoff values (1 - 4 antennas, single spacial 219 + stream) 220 + 221 + paths-ofdm: 222 + $ref: /schemas/types.yaml#/definitions/uint8-array 223 + minItems: 4 224 + maxItems: 4 225 + description: 226 + 4 half-dBm backoff values (1 - 4 antennas, single spacial 227 + stream) 228 + 229 + paths-ofdm-bf: 230 + $ref: /schemas/types.yaml#/definitions/uint8-array 231 + minItems: 4 232 + maxItems: 4 233 + description: 234 + 4 half-dBm backoff values for beamforming 235 + (1 - 4 antennas, single spacial stream) 236 + 237 + paths-ru: 238 + $ref: /schemas/types.yaml#/definitions/uint8-matrix 239 + description: 240 + Sets of half-dBm backoff values for 802.11ax rates for 241 + 1T1ss (aka 1 transmitting antenna with 1 spacial stream), 242 + 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss 243 + and 4T4ss. 244 + Each set starts with the number of channel bandwidth or 245 + resource unit settings for which the rate set applies, 246 + followed by 10 power limit values. The order of the 247 + channel resource unit settings is RU26, RU52, RU106, 248 + RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160. 249 + minItems: 1 250 + maxItems: 7 251 + items: 252 + minItems: 11 253 + maxItems: 11 254 + 255 + paths-ru-bf: 256 + $ref: /schemas/types.yaml#/definitions/uint8-matrix 257 + description: 258 + Sets of half-dBm backoff (beamforming) values for 802.11ax 259 + rates for 1T1ss (aka 1 transmitting antenna with 1 spacial 260 + stream), 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 261 + 4T3ss and 4T4ss. 262 + Each set starts with the number of channel bandwidth or 263 + resource unit settings for which the rate set applies, 264 + followed by 10 power limit values. The order of the 265 + channel resource unit settings is RU26, RU52, RU106, 266 + RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160. 267 + minItems: 1 268 + maxItems: 7 269 + items: 270 + minItems: 11 271 + maxItems: 11 218 272 219 273 txs-delta: 220 274 $ref: /schemas/types.yaml#/definitions/uint32-array
+5 -1
drivers/net/wireless/mediatek/mt76/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT76_CORE 3 3 tristate 4 4 select PAGE_POOL ··· 36 36 config MT792x_USB 37 37 tristate 38 38 select MT76_USB 39 + 40 + config MT76_NPU 41 + bool 42 + depends on MT76_CORE 39 43 40 44 source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" 41 45 source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
+2 -1
drivers/net/wireless/mediatek/mt76/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 obj-$(CONFIG_MT76_CORE) += mt76.o 3 3 obj-$(CONFIG_MT76_USB) += mt76-usb.o 4 4 obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o ··· 12 12 mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ 13 13 tx.o agg-rx.o mcu.o wed.o scan.o channel.o 14 14 15 + mt76-$(CONFIG_MT76_NPU) += npu.o 15 16 mt76-$(CONFIG_PCI) += pci.o 16 17 mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o 17 18
+1 -1
drivers/net/wireless/mediatek/mt76/agg-rx.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/channel.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> 4 4 */
+3 -3
drivers/net/wireless/mediatek/mt76/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 93 93 { 94 94 int i; 95 95 96 - seq_printf(file, "%10s:", str); 96 + seq_printf(file, "%16s:", str); 97 97 for (i = 0; i < len; i++) 98 - seq_printf(file, " %2d", val[i]); 98 + seq_printf(file, " %4d", val[i]); 99 99 seq_puts(file, "\n"); 100 100 } 101 101 EXPORT_SYMBOL_GPL(mt76_seq_puts_array);
+37 -38
drivers/net/wireless/mediatek/mt76/dma.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 6 6 #include <linux/dma-mapping.h> 7 7 #include "mt76.h" 8 8 #include "dma.h" 9 - 10 - #if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) 11 - 12 - #define Q_READ(_q, _field) ({ \ 13 - u32 _offset = offsetof(struct mt76_queue_regs, _field); \ 14 - u32 _val; \ 15 - if ((_q)->flags & MT_QFLAG_WED) \ 16 - _val = mtk_wed_device_reg_read((_q)->wed, \ 17 - ((_q)->wed_regs + \ 18 - _offset)); \ 19 - else \ 20 - _val = readl(&(_q)->regs->_field); \ 21 - _val; \ 22 - }) 23 - 24 - #define Q_WRITE(_q, _field, _val) do { \ 25 - u32 _offset = offsetof(struct mt76_queue_regs, _field); \ 26 - if ((_q)->flags & MT_QFLAG_WED) \ 27 - mtk_wed_device_reg_write((_q)->wed, \ 28 - ((_q)->wed_regs + _offset), \ 29 - _val); \ 30 - else \ 31 - writel(_val, &(_q)->regs->_field); \ 32 - } while (0) 33 - 34 - #else 35 - 36 - #define Q_READ(_q, _field) readl(&(_q)->regs->_field) 37 - #define Q_WRITE(_q, _field, _val) writel(_val, &(_q)->regs->_field) 38 - 39 - #endif 40 9 41 10 static struct mt76_txwi_cache * 42 11 mt76_alloc_txwi(struct mt76_dev *dev) ··· 189 220 mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) 190 221 { 191 222 Q_WRITE(q, desc_base, q->desc_dma); 192 - if (q->flags & MT_QFLAG_WED_RRO_EN) 223 + if ((q->flags & MT_QFLAG_WED_RRO_EN) && !mt76_npu_device_active(dev)) 193 224 Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc); 194 225 else 195 226 Q_WRITE(q, ring_size, q->ndesc); 227 + 228 + if (mt76_queue_is_npu_tx(q)) { 229 + writel(q->desc_dma, &q->regs->desc_base); 230 + writel(q->ndesc, &q->regs->ring_size); 231 + } 196 232 q->head = Q_READ(q, dma_idx); 197 233 q->tail = q->head; 198 234 } ··· 209 235 return; 210 236 211 237 if (!mt76_queue_is_wed_rro_ind(q) && 212 - !mt76_queue_is_wed_rro_rxdmad_c(q)) { 238 + !mt76_queue_is_wed_rro_rxdmad_c(q) && !mt76_queue_is_npu(q)) { 213 239 int i; 214 240 215 241 /* clear descriptors */ ··· 420 446 421 447 while (q->queued > 0 && q->tail != last) { 422 448 mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry); 449 + mt76_npu_txdesc_cleanup(q, q->tail); 423 450 mt76_queue_tx_complete(dev, q, &entry); 424 451 425 452 if (entry.txwi) { ··· 655 680 if (test_bit(MT76_RESET, &phy->state)) 656 681 goto free_skb; 657 682 683 + /* TODO: Take into account unlinear skbs */ 684 + if (mt76_npu_device_active(dev) && skb_linearize(skb)) 685 + goto free_skb; 686 + 658 687 t = mt76_get_txwi(dev); 659 688 if (!t) 660 689 goto free_skb; ··· 705 726 DMA_TO_DEVICE); 706 727 if (ret < 0) 707 728 goto unmap; 729 + 730 + if (mt76_npu_device_active(dev)) 731 + return mt76_npu_dma_add_buf(phy, q, skb, &tx_info.buf[1], txwi); 708 732 709 733 return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf, 710 734 tx_info.info, tx_info.skb, t); ··· 807 825 q->ndesc = n_desc; 808 826 q->buf_size = bufsize; 809 827 q->hw_idx = idx; 828 + q->dev = dev; 810 829 811 - size = mt76_queue_is_wed_rro_ind(q) ? sizeof(struct mt76_wed_rro_desc) 812 - : sizeof(struct mt76_desc); 830 + if (mt76_queue_is_wed_rro_ind(q)) 831 + size = sizeof(struct mt76_wed_rro_desc); 832 + else if (mt76_queue_is_npu_tx(q)) 833 + size = sizeof(struct airoha_npu_tx_dma_desc); 834 + else if (mt76_queue_is_npu_rx(q)) 835 + size = sizeof(struct airoha_npu_rx_dma_desc); 836 + else 837 + size = sizeof(struct mt76_desc); 838 + 813 839 q->desc = dmam_alloc_coherent(dev->dma_dev, q->ndesc * size, 814 840 &q->desc_dma, GFP_KERNEL); 815 841 if (!q->desc) ··· 833 843 if (ret) 834 844 return ret; 835 845 846 + mt76_npu_queue_setup(dev, q); 836 847 ret = mt76_wed_dma_setup(dev, q, false); 837 848 if (ret) 838 849 return ret; ··· 860 869 861 870 if (!q->ndesc) 862 871 return; 872 + 873 + if (mt76_queue_is_npu(q)) { 874 + mt76_npu_queue_cleanup(dev, q); 875 + return; 876 + } 863 877 864 878 do { 865 879 spin_lock_bh(&q->lock); ··· 896 900 return; 897 901 898 902 if (!mt76_queue_is_wed_rro_ind(q) && 899 - !mt76_queue_is_wed_rro_rxdmad_c(q)) { 903 + !mt76_queue_is_wed_rro_rxdmad_c(q) && !mt76_queue_is_npu(q)) { 900 904 int i; 901 905 902 906 for (i = 0; i < q->ndesc; i++) ··· 916 920 return; 917 921 918 922 mt76_dma_sync_idx(dev, q); 919 - mt76_dma_rx_fill_buf(dev, q, false); 923 + if (mt76_queue_is_npu(q)) 924 + mt76_npu_fill_rx_queue(dev, q); 925 + else 926 + mt76_dma_rx_fill(dev, q, false); 920 927 } 921 928 922 929 static void
+68 -1
drivers/net/wireless/mediatek/mt76/dma.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 45 45 #define MT_RX_INFO_LEN 4 46 46 #define MT_FCE_INFO_LEN 4 47 47 #define MT_RX_RXWI_LEN 32 48 + 49 + #if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) 50 + 51 + #define Q_READ(_q, _field) ({ \ 52 + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ 53 + u32 _val; \ 54 + if ((_q)->flags & MT_QFLAG_WED) \ 55 + _val = mtk_wed_device_reg_read((_q)->wed, \ 56 + ((_q)->wed_regs + \ 57 + _offset)); \ 58 + else \ 59 + _val = readl(&(_q)->regs->_field); \ 60 + _val; \ 61 + }) 62 + 63 + #define Q_WRITE(_q, _field, _val) do { \ 64 + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ 65 + if ((_q)->flags & MT_QFLAG_WED) \ 66 + mtk_wed_device_reg_write((_q)->wed, \ 67 + ((_q)->wed_regs + _offset), \ 68 + _val); \ 69 + else \ 70 + writel(_val, &(_q)->regs->_field); \ 71 + } while (0) 72 + 73 + #elif IS_ENABLED(CONFIG_MT76_NPU) 74 + 75 + #define Q_READ(_q, _field) ({ \ 76 + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ 77 + u32 _val = 0; \ 78 + if ((_q)->flags & MT_QFLAG_NPU) { \ 79 + struct airoha_npu *npu; \ 80 + \ 81 + rcu_read_lock(); \ 82 + npu = rcu_dereference(q->dev->mmio.npu); \ 83 + if (npu) \ 84 + regmap_read(npu->regmap, \ 85 + ((_q)->wed_regs + _offset), &_val); \ 86 + rcu_read_unlock(); \ 87 + } else { \ 88 + _val = readl(&(_q)->regs->_field); \ 89 + } \ 90 + _val; \ 91 + }) 92 + 93 + #define Q_WRITE(_q, _field, _val) do { \ 94 + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ 95 + if ((_q)->flags & MT_QFLAG_NPU) { \ 96 + struct airoha_npu *npu; \ 97 + \ 98 + rcu_read_lock(); \ 99 + npu = rcu_dereference(q->dev->mmio.npu); \ 100 + if (npu) \ 101 + regmap_write(npu->regmap, \ 102 + ((_q)->wed_regs + _offset), _val); \ 103 + rcu_read_unlock(); \ 104 + } else { \ 105 + writel(_val, &(_q)->regs->_field); \ 106 + } \ 107 + } while (0) 108 + 109 + #else 110 + 111 + #define Q_READ(_q, _field) readl(&(_q)->regs->_field) 112 + #define Q_WRITE(_q, _field, _val) writel(_val, &(_q)->regs->_field) 113 + 114 + #endif 48 115 49 116 struct mt76_desc { 50 117 __le32 buf0;
+58 -19
drivers/net/wireless/mediatek/mt76/eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 253 253 return prop->value; 254 254 } 255 255 256 + static const s8 * 257 + mt76_get_of_array_s8(struct device_node *np, char *name, size_t *len, int min) 258 + { 259 + struct property *prop = of_find_property(np, name, NULL); 260 + 261 + if (!prop || !prop->value || prop->length < min) 262 + return NULL; 263 + 264 + *len = prop->length; 265 + 266 + return prop->value; 267 + } 268 + 256 269 struct device_node * 257 270 mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) 258 271 { ··· 307 294 } 308 295 309 296 static void 310 - mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data, 297 + mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data, 311 298 s8 target_power, s8 nss_delta, s8 *max_power) 312 299 { 313 300 int i; ··· 316 303 return; 317 304 318 305 for (i = 0; i < pwr_len; i++) { 319 - pwr[i] = min_t(s8, target_power, 320 - be32_to_cpu(data[i]) + nss_delta); 306 + pwr[i] = min_t(s8, target_power, data[i] + nss_delta); 321 307 *max_power = max(*max_power, pwr[i]); 322 308 } 323 309 } 324 310 325 311 static void 326 312 mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, 327 - const __be32 *data, size_t len, s8 target_power, 328 - s8 nss_delta, s8 *max_power) 313 + const s8 *data, size_t len, s8 target_power, 314 + s8 nss_delta) 329 315 { 330 316 int i, cur; 317 + s8 max_power = -128; 331 318 332 319 if (!data) 333 320 return; 334 321 335 - len /= 4; 336 - cur = be32_to_cpu(data[0]); 322 + cur = data[0]; 337 323 for (i = 0; i < pwr_num; i++) { 338 324 if (len < pwr_len + 1) 339 325 break; 340 326 341 327 mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1, 342 - target_power, nss_delta, max_power); 328 + target_power, nss_delta, &max_power); 343 329 if (--cur > 0) 344 330 continue; 345 331 ··· 347 335 if (!len) 348 336 break; 349 337 350 - cur = be32_to_cpu(data[0]); 338 + cur = data[0]; 351 339 } 352 340 } 353 341 ··· 358 346 { 359 347 struct mt76_dev *dev = phy->dev; 360 348 struct device_node *np; 361 - const __be32 *val; 349 + const s8 *val; 362 350 char name[16]; 363 351 u32 mcs_rates = dev->drv->mcs_rates; 364 352 u32 ru_rates = ARRAY_SIZE(dest->ru[0]); 365 353 char band; 366 354 size_t len; 367 355 s8 max_power = 0; 356 + s8 max_power_backoff = -127; 368 357 s8 txs_delta; 358 + int n_chains = hweight16(phy->chainmask); 359 + s8 target_power_combine = target_power + mt76_tx_power_path_delta(n_chains); 369 360 370 361 if (!mcs_rates) 371 362 mcs_rates = 10; 372 363 373 - memset(dest, target_power, sizeof(*dest)); 364 + memset(dest, target_power, sizeof(*dest) - sizeof(dest->path)); 365 + memset(&dest->path, 0, sizeof(dest->path)); 374 366 375 367 if (!IS_ENABLED(CONFIG_OF)) 376 368 return target_power; ··· 408 392 409 393 txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask)); 410 394 411 - val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck)); 395 + val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck)); 412 396 mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val, 413 397 target_power, txs_delta, &max_power); 414 398 415 - val = mt76_get_of_array(np, "rates-ofdm", 416 - &len, ARRAY_SIZE(dest->ofdm)); 399 + val = mt76_get_of_array_s8(np, "rates-ofdm", 400 + &len, ARRAY_SIZE(dest->ofdm)); 417 401 mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val, 418 402 target_power, txs_delta, &max_power); 419 403 420 - val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1); 404 + val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1); 421 405 mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]), 422 406 ARRAY_SIZE(dest->mcs), val, len, 423 - target_power, txs_delta, &max_power); 407 + target_power, txs_delta); 424 408 425 - val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1); 409 + val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1); 426 410 mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]), 427 411 ARRAY_SIZE(dest->ru), val, len, 428 - target_power, txs_delta, &max_power); 412 + target_power, txs_delta); 413 + 414 + max_power_backoff = max_power; 415 + val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck)); 416 + mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val, 417 + target_power_combine, txs_delta, &max_power_backoff); 418 + 419 + val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm)); 420 + mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val, 421 + target_power_combine, txs_delta, &max_power_backoff); 422 + 423 + val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf)); 424 + mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val, 425 + target_power_combine, txs_delta, &max_power_backoff); 426 + 427 + val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1); 428 + mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]), 429 + ARRAY_SIZE(dest->path.ru), val, len, 430 + target_power_combine, txs_delta); 431 + 432 + val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1); 433 + mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]), 434 + ARRAY_SIZE(dest->path.ru_bf), val, len, 435 + target_power_combine, txs_delta); 429 436 430 437 return max_power; 431 438 }
+6 -4
drivers/net/wireless/mediatek/mt76/mac80211.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 630 630 case MT_RXQ_MAIN: 631 631 case MT_RXQ_BAND1: 632 632 case MT_RXQ_BAND2: 633 + case MT_RXQ_NPU0: 634 + case MT_RXQ_NPU1: 633 635 pp_params.pool_size = 256; 634 636 break; 635 637 default: ··· 816 814 destroy_workqueue(dev->wq); 817 815 dev->wq = NULL; 818 816 } 817 + mt76_npu_deinit(dev); 819 818 ieee80211_free_hw(dev->hw); 820 819 } 821 820 EXPORT_SYMBOL_GPL(mt76_free_device); ··· 849 846 rcu_assign_pointer(dev->wcid[i], NULL); 850 847 } 851 848 rcu_read_unlock(); 852 - 853 - mt76_abort_scan(dev); 854 849 855 850 INIT_LIST_HEAD(&dev->wcid_list); 856 851 INIT_LIST_HEAD(&dev->sta_poll_list); ··· 1554 1553 1555 1554 while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) { 1556 1555 mt76_check_sta(dev, skb); 1557 - if (mtk_wed_device_active(&dev->mmio.wed)) 1556 + if (mtk_wed_device_active(&dev->mmio.wed) || 1557 + mt76_npu_device_active(dev)) 1558 1558 __skb_queue_tail(&frames, skb); 1559 1559 else 1560 1560 mt76_rx_aggr_reorder(skb, &frames);
+1 -1
drivers/net/wireless/mediatek/mt76/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2019 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+11 -3
drivers/net/wireless/mediatek/mt76/mmio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 33 33 static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset, 34 34 const void *data, int len) 35 35 { 36 - __iowrite32_copy(dev->mmio.regs + offset, data, DIV_ROUND_UP(len, 4)); 36 + int i; 37 + 38 + for (i = 0; i < ALIGN(len, 4); i += 4) 39 + writel(get_unaligned_le32(data + i), 40 + dev->mmio.regs + offset + i); 37 41 } 38 42 39 43 static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset, 40 44 void *data, int len) 41 45 { 42 - __ioread32_copy(data, dev->mmio.regs + offset, DIV_ROUND_UP(len, 4)); 46 + int i; 47 + 48 + for (i = 0; i < ALIGN(len, 4); i += 4) 49 + put_unaligned_le32(readl(dev->mmio.regs + offset + i), 50 + data + i); 43 51 } 44 52 45 53 static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,
+157 -2
drivers/net/wireless/mediatek/mt76/mt76.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 13 13 #include <linux/leds.h> 14 14 #include <linux/usb.h> 15 15 #include <linux/average.h> 16 + #include <linux/soc/airoha/airoha_offload.h> 16 17 #include <linux/soc/mediatek/mtk_wed.h> 17 18 #include <net/mac80211.h> 18 19 #include <net/page_pool/helpers.h> ··· 35 34 #define MT_QFLAG_WED_RRO BIT(6) 36 35 #define MT_QFLAG_WED_RRO_EN BIT(7) 37 36 #define MT_QFLAG_EMI_EN BIT(8) 37 + #define MT_QFLAG_NPU BIT(9) 38 38 39 39 #define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \ 40 40 FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ ··· 49 47 #define MT_WED_RRO_Q_MSDU_PG(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n) 50 48 #define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0) 51 49 #define MT_WED_RRO_Q_RXDMAD_C __MT_WED_RRO_Q(MT76_WED_RRO_Q_RXDMAD_C, 0) 50 + 51 + #define __MT_NPU_Q(_type, _n) (MT_QFLAG_NPU | \ 52 + FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ 53 + FIELD_PREP(MT_QFLAG_WED_RING, _n)) 54 + #define MT_NPU_Q_TX(_n) __MT_NPU_Q(MT76_WED_Q_TX, _n) 55 + #define MT_NPU_Q_RX(_n) __MT_NPU_Q(MT76_WED_Q_RX, _n) 52 56 53 57 struct mt76_dev; 54 58 struct mt76_phy; ··· 147 139 MT_RXQ_TXFREE_BAND2, 148 140 MT_RXQ_RRO_IND, 149 141 MT_RXQ_RRO_RXDMAD_C, 142 + MT_RXQ_NPU0, 143 + MT_RXQ_NPU1, 150 144 __MT_RXQ_MAX 151 145 }; 152 146 ··· 257 247 __le16 *emi_cpu_idx; 258 248 259 249 struct mtk_wed_device *wed; 250 + struct mt76_dev *dev; 260 251 u32 wed_regs; 261 252 262 253 dma_addr_t desc_dma; ··· 717 706 struct mtk_wed_device wed_hif2; 718 707 struct completion wed_reset; 719 708 struct completion wed_reset_complete; 709 + 710 + struct airoha_ppe_dev __rcu *ppe_dev; 711 + struct airoha_npu __rcu *npu; 712 + phys_addr_t phy_addr; 713 + int npu_type; 720 714 }; 721 715 722 716 struct mt76_rx_status { ··· 959 943 struct idr token; 960 944 u16 wed_token_count; 961 945 u16 token_count; 946 + u16 token_start; 962 947 u16 token_size; 963 948 964 949 spinlock_t rx_token_lock; ··· 1130 1113 s8 mcs[4][10]; 1131 1114 s8 ru[7][12]; 1132 1115 s8 eht[16][16]; 1116 + 1117 + struct { 1118 + s8 cck[4]; 1119 + s8 ofdm[4]; 1120 + s8 ofdm_bf[4]; 1121 + s8 ru[7][10]; 1122 + s8 ru_bf[7][10]; 1123 + } path; 1133 1124 }; 1134 1125 1135 1126 struct mt76_ethtool_worker_info { ··· 1276 1251 1277 1252 #define mt76_dereference(p, dev) \ 1278 1253 rcu_dereference_protected(p, lockdep_is_held(&(dev)->mutex)) 1254 + 1255 + static inline struct mt76_dev *mt76_wed_to_dev(struct mtk_wed_device *wed) 1256 + { 1257 + #ifdef CONFIG_NET_MEDIATEK_SOC_WED 1258 + if (wed->wlan.hif2) 1259 + return container_of(wed, struct mt76_dev, mmio.wed_hif2); 1260 + #endif /* CONFIG_NET_MEDIATEK_SOC_WED */ 1261 + return container_of(wed, struct mt76_dev, mmio.wed); 1262 + } 1279 1263 1280 1264 static inline struct mt76_wcid * 1281 1265 __mt76_wcid_ptr(struct mt76_dev *dev, u16 idx) ··· 1632 1598 int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state); 1633 1599 int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len); 1634 1600 1601 + #ifdef CONFIG_MT76_NPU 1602 + void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb, 1603 + u32 info); 1604 + int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q, 1605 + struct sk_buff *skb, struct mt76_queue_buf *buf, 1606 + void *txwi_ptr); 1607 + int mt76_npu_rx_queue_init(struct mt76_dev *dev, struct mt76_queue *q); 1608 + int mt76_npu_fill_rx_queue(struct mt76_dev *dev, struct mt76_queue *q); 1609 + void mt76_npu_queue_cleanup(struct mt76_dev *dev, struct mt76_queue *q); 1610 + void mt76_npu_disable_irqs(struct mt76_dev *dev); 1611 + int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type); 1612 + void mt76_npu_deinit(struct mt76_dev *dev); 1613 + void mt76_npu_queue_setup(struct mt76_dev *dev, struct mt76_queue *q); 1614 + void mt76_npu_txdesc_cleanup(struct mt76_queue *q, int index); 1615 + int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1616 + struct net_device *dev, enum tc_setup_type type, 1617 + void *type_data); 1618 + #else 1619 + static inline void mt76_npu_check_ppe(struct mt76_dev *dev, 1620 + struct sk_buff *skb, u32 info) 1621 + { 1622 + } 1623 + 1624 + static inline int mt76_npu_dma_add_buf(struct mt76_phy *phy, 1625 + struct mt76_queue *q, 1626 + struct sk_buff *skb, 1627 + struct mt76_queue_buf *buf, 1628 + void *txwi_ptr) 1629 + { 1630 + return -EOPNOTSUPP; 1631 + } 1632 + 1633 + static inline int mt76_npu_fill_rx_queue(struct mt76_dev *dev, 1634 + struct mt76_queue *q) 1635 + { 1636 + return 0; 1637 + } 1638 + 1639 + static inline void mt76_npu_queue_cleanup(struct mt76_dev *dev, 1640 + struct mt76_queue *q) 1641 + { 1642 + } 1643 + 1644 + static inline void mt76_npu_disable_irqs(struct mt76_dev *dev) 1645 + { 1646 + } 1647 + 1648 + static inline int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, 1649 + int type) 1650 + { 1651 + return 0; 1652 + } 1653 + 1654 + static inline void mt76_npu_deinit(struct mt76_dev *dev) 1655 + { 1656 + } 1657 + 1658 + static inline void mt76_npu_queue_setup(struct mt76_dev *dev, 1659 + struct mt76_queue *q) 1660 + { 1661 + } 1662 + 1663 + static inline void mt76_npu_txdesc_cleanup(struct mt76_queue *q, 1664 + int index) 1665 + { 1666 + } 1667 + 1668 + static inline int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, 1669 + struct ieee80211_vif *vif, 1670 + struct net_device *dev, 1671 + enum tc_setup_type type, 1672 + void *type_data) 1673 + { 1674 + return -EOPNOTSUPP; 1675 + } 1676 + #endif /* CONFIG_MT76_NPU */ 1677 + 1678 + static inline bool mt76_npu_device_active(struct mt76_dev *dev) 1679 + { 1680 + return !!rcu_access_pointer(dev->mmio.npu); 1681 + } 1682 + 1683 + static inline bool mt76_ppe_device_active(struct mt76_dev *dev) 1684 + { 1685 + return !!rcu_access_pointer(dev->mmio.ppe_dev); 1686 + } 1687 + 1688 + static inline int mt76_npu_send_msg(struct airoha_npu *npu, int ifindex, 1689 + enum airoha_npu_wlan_set_cmd cmd, 1690 + u32 val, gfp_t gfp) 1691 + { 1692 + return airoha_npu_wlan_send_msg(npu, ifindex, cmd, &val, sizeof(val), 1693 + gfp); 1694 + } 1695 + 1696 + static inline int mt76_npu_get_msg(struct airoha_npu *npu, int ifindex, 1697 + enum airoha_npu_wlan_get_cmd cmd, 1698 + u32 *val, gfp_t gfp) 1699 + { 1700 + return airoha_npu_wlan_get_msg(npu, ifindex, cmd, val, sizeof(*val), 1701 + gfp); 1702 + } 1703 + 1635 1704 static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable) 1636 1705 { 1637 1706 #ifdef CONFIG_NL80211_TESTMODE ··· 1976 1839 return q->flags & MT_QFLAG_EMI_EN; 1977 1840 } 1978 1841 1842 + static inline bool mt76_queue_is_npu(struct mt76_queue *q) 1843 + { 1844 + return q->flags & MT_QFLAG_NPU; 1845 + } 1846 + 1847 + static inline bool mt76_queue_is_npu_tx(struct mt76_queue *q) 1848 + { 1849 + return mt76_queue_is_npu(q) && 1850 + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TX; 1851 + } 1852 + 1853 + static inline bool mt76_queue_is_npu_rx(struct mt76_queue *q) 1854 + { 1855 + return mt76_queue_is_npu(q) && 1856 + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX; 1857 + } 1858 + 1979 1859 struct mt76_txwi_cache * 1980 1860 mt76_token_release(struct mt76_dev *dev, int token, bool *wake); 1981 1861 int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi); ··· 2014 1860 { 2015 1861 struct page *page; 2016 1862 2017 - page = page_pool_dev_alloc_frag(q->page_pool, offset, size); 1863 + page = page_pool_alloc_frag(q->page_pool, offset, size, 1864 + GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32); 2018 1865 if (!page) 2019 1866 return NULL; 2020 1867
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT7603E 3 3 tristate "MediaTek MT7603E (PCIe) and MT76x8 WLAN support" 4 4 select MT76_CORE
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 obj-$(CONFIG_MT7603E) += mt7603e.o 3 3 4 4 mt7603e-y := \
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7603.h" 4 4
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/core.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7603.h" 4 4 #include "../trace.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7603.h" 4 4
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/dma.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7603.h" 4 4 #include "mac.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/of.h> 4 4 #include "mt7603.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 3 3 #ifndef __MT7603_EEPROM_H 4 4 #define __MT7603_EEPROM_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/etherdevice.h> 4 4 #include "mt7603.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/etherdevice.h> 4 4 #include <linux/timekeeping.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 3 3 #ifndef __MT7603_MAC_H 4 4 #define __MT7603_MAC_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/etherdevice.h> 4 4 #include <linux/platform_device.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/firmware.h> 4 4 #include "mt7603.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 3 3 #ifndef __MT7603_MCU_H 4 4 #define __MT7603_MCU_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 3 3 #ifndef __MT7603_H 4 4 #define __MT7603_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/kernel.h> 4 4 #include <linux/module.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 3 3 #ifndef __MT7603_REGS_H 4 4 #define __MT7603_REGS_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7603/soc.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include <linux/kernel.h> 4 4 #include <linux/module.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 config MT7615_COMMON 4 4 tristate
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/Makefile
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 obj-$(CONFIG_MT7615_COMMON) += mt7615-common.o 4 4 obj-$(CONFIG_MT7615E) += mt7615e.o
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7615.h" 4 4
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/dma.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2019 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7615_EEPROM_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Roy Luo <royluo@google.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2019 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7615_MAC_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Roy Luo <royluo@google.com>
+4 -2
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Roy Luo <royluo@google.com> ··· 874 874 wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, 875 875 WTBL_RESET_AND_SET, NULL, 876 876 &wskb); 877 - if (IS_ERR(wtbl_hdr)) 877 + if (IS_ERR(wtbl_hdr)) { 878 + dev_kfree_skb(sskb); 878 879 return PTR_ERR(wtbl_hdr); 880 + } 879 881 880 882 if (enable) { 881 883 mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, wskb, vif, sta,
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2019 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7615_MCU_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/kernel.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2019 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7615_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Roy Luo <royluo@google.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2019 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7615_REGS_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * Author: Felix Fietkau <nbd@nbd.name>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/soc.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/testmode.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */ 3 3 4 4 #include "mt7615.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/trace.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/usb.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2019 MediaTek Inc. 3 3 * 4 4 * Author: Felix Fietkau <nbd@nbd.name>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76_connac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT76_CONNAC_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2022 MediaTek Inc. */ 3 3 4 4 #ifndef __MT76_CONNAC2_MAC_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include "mt76_connac.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT76_CONNAC3_MAC_H
+12 -9
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include "mt76_connac.h" ··· 297 297 struct ieee80211_bss_conf *conf, 298 298 bool beacon, bool mcast) 299 299 { 300 - struct mt76_vif_link *mvif = mt76_vif_conf_link(mphy->dev, conf->vif, conf); 301 - struct cfg80211_chan_def *chandef = mvif->ctx ? 302 - &mvif->ctx->def : &mphy->chandef; 303 - u8 nss = 0, mode = 0, band = chandef->chan->band; 304 - int rateidx = 0, mcast_rate; 305 - int offset = 0; 300 + u8 nss = 0, mode = 0, band = NL80211_BAND_2GHZ; 301 + int rateidx = 0, offset = 0, mcast_rate; 302 + struct cfg80211_chan_def *chandef; 303 + struct mt76_vif_link *mvif; 306 304 307 305 if (!conf) 308 306 goto legacy; 307 + 308 + mvif = mt76_vif_conf_link(mphy->dev, conf->vif, conf); 309 + chandef = mvif->ctx ? &mvif->ctx->def : &mphy->chandef; 310 + band = chandef->chan->band; 309 311 310 312 if (is_mt7921(mphy->dev)) { 311 313 rateidx = ffs(conf->basic_rates) - 1; ··· 586 584 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 587 585 bool multicast = ieee80211_is_data(hdr->frame_control) && 588 586 is_multicast_ether_addr(hdr->addr1); 589 - u16 rate = mt76_connac2_mac_tx_rate_val(mphy, &vif->bss_conf, beacon, 590 - multicast); 587 + u16 rate = mt76_connac2_mac_tx_rate_val(mphy, 588 + vif ? &vif->bss_conf : NULL, 589 + beacon, multicast); 591 590 u32 val = MT_TXD6_FIXED_BW; 592 591 593 592 /* hardware won't add HTC for mgmt/ctrl frame */
+7 -3
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/firmware.h> ··· 1974 1974 .resp_type = 0, 1975 1975 }; 1976 1976 1977 - memcpy(req.data, "assert", 7); 1977 + strscpy(req.data, "assert"); 1978 1978 1979 1979 return mt76_mcu_send_msg(dev, MCU_CE_CMD(CHIP_CONFIG), 1980 1980 &req, sizeof(req), false); ··· 3101 3101 int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096; 3102 3102 const struct mt76_connac2_patch_hdr *hdr; 3103 3103 const struct firmware *fw = NULL; 3104 + char build_date[17]; 3104 3105 3105 3106 sem = mt76_connac_mcu_patch_sem_ctrl(dev, true); 3106 3107 switch (sem) { ··· 3125 3124 } 3126 3125 3127 3126 hdr = (const void *)fw->data; 3127 + strscpy(build_date, hdr->build_date, sizeof(build_date)); 3128 + build_date[16] = '\0'; 3129 + strim(build_date); 3128 3130 dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", 3129 - be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); 3131 + be32_to_cpu(hdr->hw_sw_ver), build_date); 3130 3132 3131 3133 for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { 3132 3134 struct mt76_connac2_patch_sec *sec;
+3 -1
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT76_CONNAC_MCU_H ··· 1062 1062 MCU_UNI_EVENT_ROC = 0x27, 1063 1063 MCU_UNI_EVENT_TX_DONE = 0x2d, 1064 1064 MCU_UNI_EVENT_THERMAL = 0x35, 1065 + MCU_UNI_EVENT_RSSI_MONITOR = 0x41, 1065 1066 MCU_UNI_EVENT_NIC_CAPAB = 0x43, 1066 1067 MCU_UNI_EVENT_WED_RRO = 0x57, 1067 1068 MCU_UNI_EVENT_PER_STA_INFO = 0x6d, ··· 1301 1300 MCU_UNI_CMD_THERMAL = 0x35, 1302 1301 MCU_UNI_CMD_VOW = 0x37, 1303 1302 MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40, 1303 + MCU_UNI_CMD_RSSI_MONITOR = 0x41, 1304 1304 MCU_UNI_CMD_TESTMODE_CTRL = 0x46, 1305 1305 MCU_UNI_CMD_RRO = 0x57, 1306 1306 MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_dma.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_trace.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_trace.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x02_util.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> 4 4 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT76x2_COMMON 3 3 tristate 4 4 select MT76x02_LIB
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o 3 3 obj-$(CONFIG_MT76x2E) += mt76x2e.o 4 4 obj-$(CONFIG_MT76x2U) += mt76x2u.o
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT7915E 3 3 tristate "MediaTek MT7915E (PCIe) support" 4 4 select MT76_CONNAC_LIB
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/Makefile
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 obj-$(CONFIG_MT7915E) += mt7915e.o 4 4
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/coredump.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2022 MediaTek Inc. */ 3 3 4 4 #include <linux/devcoredump.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/coredump.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2022 MediaTek Inc. */ 3 3 4 4 #ifndef _COREDUMP_H_
+71 -5
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/relay.h> ··· 1008 1008 if (!buf) 1009 1009 return -ENOMEM; 1010 1010 1011 - ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr)); 1011 + ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr), TX_POWER_INFO_RATE); 1012 1012 if (ret) 1013 1013 goto out; 1014 1014 ··· 1118 1118 1119 1119 mutex_lock(&dev->mt76.mutex); 1120 1120 ret = mt7915_mcu_get_txpower_sku(phy, req.txpower_sku, 1121 - sizeof(req.txpower_sku)); 1121 + sizeof(req.txpower_sku), TX_POWER_INFO_RATE); 1122 1122 if (ret) 1123 1123 goto out; 1124 1124 ··· 1160 1160 return ret ? ret : count; 1161 1161 } 1162 1162 1163 - static const struct file_operations mt7915_rate_txpower_fops = { 1163 + static const struct file_operations mt7915_txpower_fops = { 1164 1164 .write = mt7915_rate_txpower_set, 1165 1165 .read = mt7915_rate_txpower_get, 1166 1166 .open = simple_open, 1167 1167 .owner = THIS_MODULE, 1168 1168 .llseek = default_llseek, 1169 1169 }; 1170 + 1171 + static int 1172 + mt7915_path_txpower_show(struct seq_file *file) 1173 + { 1174 + struct mt7915_phy *phy = file->private; 1175 + s8 txpower[MT7915_SKU_PATH_NUM], *buf = txpower; 1176 + int ret; 1177 + 1178 + #define PATH_POWER_SHOW(_name, _len, _skip) do { \ 1179 + size_t __len = (_len); \ 1180 + if (_skip) { \ 1181 + buf -= 1; \ 1182 + *buf = 0; \ 1183 + } \ 1184 + mt76_seq_puts_array(file, _name, buf, __len); \ 1185 + buf += __len; \ 1186 + } while (0) 1187 + 1188 + seq_printf(file, "\n%*c", 18, ' '); 1189 + seq_puts(file, "1T1S/2T1S/3T1S/4T1S/2T2S/3T2S/4T2S/3T3S/4T3S/4T4S\n"); 1190 + ret = mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower), 1191 + TX_POWER_INFO_PATH); 1192 + if (ret) 1193 + return ret; 1194 + 1195 + PATH_POWER_SHOW("CCK", 4, 0); 1196 + PATH_POWER_SHOW("OFDM", 4, 0); 1197 + PATH_POWER_SHOW("BF-OFDM", 4, 1); 1198 + 1199 + PATH_POWER_SHOW("HT/VHT20", 10, 0); 1200 + PATH_POWER_SHOW("BF-HT/VHT20", 10, 1); 1201 + PATH_POWER_SHOW("HT/VHT40", 10, 0); 1202 + PATH_POWER_SHOW("BF-HT/VHT40", 10, 1); 1203 + 1204 + PATH_POWER_SHOW("BW20/RU242", 10, 0); 1205 + PATH_POWER_SHOW("BF-BW20/RU242", 10, 1); 1206 + PATH_POWER_SHOW("BW40/RU484", 10, 0); 1207 + PATH_POWER_SHOW("BF-BW40/RU484", 10, 1); 1208 + PATH_POWER_SHOW("BW80/RU996", 10, 0); 1209 + PATH_POWER_SHOW("BF-BW80/RU996", 10, 1); 1210 + PATH_POWER_SHOW("BW160/RU2x996", 10, 0); 1211 + PATH_POWER_SHOW("BF-BW160/RU2x996", 10, 1); 1212 + PATH_POWER_SHOW("RU26", 10, 0); 1213 + PATH_POWER_SHOW("BF-RU26", 10, 0); 1214 + PATH_POWER_SHOW("RU52", 10, 0); 1215 + PATH_POWER_SHOW("BF-RU52", 10, 0); 1216 + PATH_POWER_SHOW("RU106", 10, 0); 1217 + PATH_POWER_SHOW("BF-RU106", 10, 0); 1218 + #undef PATH_POWER_SHOW 1219 + 1220 + return 0; 1221 + } 1222 + 1223 + static int 1224 + mt7915_txpower_path_show(struct seq_file *file, void *data) 1225 + { 1226 + struct mt7915_phy *phy = file->private; 1227 + 1228 + seq_printf(file, "\nBand %d\n", phy != &phy->dev->phy); 1229 + 1230 + return mt7915_path_txpower_show(file); 1231 + } 1232 + 1233 + DEFINE_SHOW_ATTRIBUTE(mt7915_txpower_path); 1170 1234 1171 1235 static int 1172 1236 mt7915_twt_stats(struct seq_file *s, void *data) ··· 1318 1254 debugfs_create_file("implicit_txbf", 0600, dir, dev, 1319 1255 &fops_implicit_txbf); 1320 1256 debugfs_create_file("txpower_sku", 0400, dir, phy, 1321 - &mt7915_rate_txpower_fops); 1257 + &mt7915_txpower_fops); 1258 + debugfs_create_file("txpower_path", 0400, dir, phy, 1259 + &mt7915_txpower_path_fops); 1322 1260 debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, 1323 1261 mt7915_twt_stats); 1324 1262 debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/dma.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include "mt7915.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/firmware.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7915_EEPROM_H
+8 -1
drivers/net/wireless/mediatek/mt76/mt7915/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h> ··· 289 289 int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band); 290 290 struct mt76_power_limits limits; 291 291 292 + phy->sku_limit_en = true; 293 + phy->sku_path_en = true; 292 294 for (i = 0; i < sband->n_channels; i++) { 293 295 struct ieee80211_channel *chan = &sband->channels[i]; 294 296 u32 target_power = 0; ··· 307 305 target_power = mt76_get_rate_power_limits(phy->mt76, chan, 308 306 &limits, 309 307 target_power); 308 + 309 + /* MT7915N can not enable Backoff table without setting value in dts */ 310 + if (!limits.path.ofdm[0]) 311 + phy->sku_path_en = false; 312 + 310 313 target_power += path_delta; 311 314 target_power = DIV_ROUND_UP(target_power, 2); 312 315 chan->max_power = min_t(int, chan->max_reg_power,
+3 -1
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h> ··· 1450 1450 cancel_delayed_work_sync(&dev->mphy.mac_work); 1451 1451 if (ext_phy) 1452 1452 cancel_delayed_work_sync(&ext_phy->mac_work); 1453 + 1454 + mt76_abort_scan(&dev->mt76); 1453 1455 1454 1456 mutex_lock(&dev->mt76.mutex); 1455 1457 for (i = 0; i < 10; i++) {
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7915_MAC_H
+2 -2
drivers/net/wireless/mediatek/mt76/mt7915/main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h> ··· 73 73 if (ret) 74 74 goto out; 75 75 76 - ret = mt7915_mcu_set_sku_en(phy, true); 76 + ret = mt7915_mcu_set_sku_en(phy); 77 77 if (ret) 78 78 goto out; 79 79
+143 -41
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/fs.h> ··· 3336 3336 int ret; 3337 3337 s8 txpower_sku[MT7915_SKU_RATE_NUM]; 3338 3338 3339 - ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku)); 3339 + ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku), 3340 + TX_POWER_INFO_RATE); 3340 3341 if (ret) 3341 3342 return ret; 3342 3343 ··· 3377 3376 sizeof(req), true); 3378 3377 } 3379 3378 3379 + static void 3380 + mt7915_update_txpower(struct mt7915_phy *phy, int tx_power) 3381 + { 3382 + struct mt76_phy *mphy = phy->mt76; 3383 + struct ieee80211_channel *chan = mphy->main_chandef.chan; 3384 + int chain_idx, val, e2p_power_limit = 0; 3385 + 3386 + if (!chan) { 3387 + mphy->txpower_cur = tx_power; 3388 + return; 3389 + } 3390 + 3391 + for (chain_idx = 0; chain_idx < hweight16(mphy->chainmask); chain_idx++) { 3392 + val = mt7915_eeprom_get_target_power(phy->dev, chan, chain_idx); 3393 + val += mt7915_eeprom_get_power_delta(phy->dev, chan->band); 3394 + 3395 + e2p_power_limit = max_t(int, e2p_power_limit, val); 3396 + } 3397 + 3398 + if (phy->sku_limit_en) 3399 + mphy->txpower_cur = min_t(int, e2p_power_limit, tx_power); 3400 + else 3401 + mphy->txpower_cur = e2p_power_limit; 3402 + } 3403 + 3380 3404 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy) 3381 3405 { 3406 + #define TX_POWER_LIMIT_TABLE_RATE 0 3407 + #define TX_POWER_LIMIT_TABLE_PATH 1 3382 3408 struct mt7915_dev *dev = phy->dev; 3383 3409 struct mt76_phy *mphy = phy->mt76; 3384 3410 struct ieee80211_hw *hw = mphy->hw; 3385 - struct mt7915_mcu_txpower_sku req = { 3411 + struct mt7915_sku_val { 3412 + u8 format_id; 3413 + u8 limit_type; 3414 + u8 band_idx; 3415 + } __packed hdr = { 3386 3416 .format_id = TX_POWER_LIMIT_TABLE, 3417 + .limit_type = TX_POWER_LIMIT_TABLE_RATE, 3387 3418 .band_idx = phy->mt76->band_idx, 3388 3419 }; 3389 - struct mt76_power_limits limits_array; 3390 - s8 *la = (s8 *)&limits_array; 3391 - int i, idx; 3392 - int tx_power; 3420 + int i, ret, tx_power; 3421 + const u8 *len = mt7915_sku_group_len; 3422 + struct mt76_power_limits la = {}; 3423 + struct sk_buff *skb; 3393 3424 3394 3425 tx_power = mt76_get_power_bound(mphy, hw->conf.power_level); 3395 - tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, 3396 - &limits_array, tx_power); 3397 - mphy->txpower_cur = tx_power; 3398 - 3399 - for (i = 0, idx = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) { 3400 - u8 mcs_num, len = mt7915_sku_group_len[i]; 3401 - int j; 3402 - 3403 - if (i >= SKU_HT_BW20 && i <= SKU_VHT_BW160) { 3404 - mcs_num = 10; 3405 - 3406 - if (i == SKU_HT_BW20 || i == SKU_VHT_BW20) 3407 - la = (s8 *)&limits_array + 12; 3408 - } else { 3409 - mcs_num = len; 3410 - } 3411 - 3412 - for (j = 0; j < min_t(u8, mcs_num, len); j++) 3413 - req.txpower_sku[idx + j] = la[j]; 3414 - 3415 - la += mcs_num; 3416 - idx += len; 3426 + if (phy->sku_limit_en) { 3427 + tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, 3428 + &la, tx_power); 3429 + mt7915_update_txpower(phy, tx_power); 3430 + } else { 3431 + mt7915_update_txpower(phy, tx_power); 3432 + return 0; 3417 3433 } 3418 3434 3419 - return mt76_mcu_send_msg(&dev->mt76, 3420 - MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, 3421 - sizeof(req), true); 3435 + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, 3436 + sizeof(hdr) + MT7915_SKU_RATE_NUM); 3437 + if (!skb) 3438 + return -ENOMEM; 3439 + 3440 + skb_put_data(skb, &hdr, sizeof(hdr)); 3441 + skb_put_data(skb, &la.cck, len[SKU_CCK] + len[SKU_OFDM]); 3442 + skb_put_data(skb, &la.mcs[0], len[SKU_HT_BW20]); 3443 + skb_put_data(skb, &la.mcs[1], len[SKU_HT_BW40]); 3444 + 3445 + /* vht */ 3446 + for (i = 0; i < 4; i++) { 3447 + skb_put_data(skb, &la.mcs[i], sizeof(la.mcs[i])); 3448 + skb_put_zero(skb, 2); /* padding */ 3449 + } 3450 + 3451 + /* he */ 3452 + skb_put_data(skb, &la.ru[0], sizeof(la.ru)); 3453 + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, 3454 + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), true); 3455 + if (ret) 3456 + return ret; 3457 + 3458 + /* only set per-path power table when it's configured */ 3459 + if (!phy->sku_path_en) 3460 + return 0; 3461 + 3462 + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, 3463 + sizeof(hdr) + MT7915_SKU_PATH_NUM); 3464 + if (!skb) 3465 + return -ENOMEM; 3466 + 3467 + hdr.limit_type = TX_POWER_LIMIT_TABLE_PATH; 3468 + skb_put_data(skb, &hdr, sizeof(hdr)); 3469 + skb_put_data(skb, &la.path.cck, sizeof(la.path.cck)); 3470 + skb_put_data(skb, &la.path.ofdm, sizeof(la.path.ofdm)); 3471 + skb_put_data(skb, &la.path.ofdm_bf[1], sizeof(la.path.ofdm_bf) - 1); 3472 + 3473 + /* HT20 and HT40 */ 3474 + skb_put_data(skb, &la.path.ru[3], sizeof(la.path.ru[3])); 3475 + skb_put_data(skb, &la.path.ru_bf[3][1], sizeof(la.path.ru_bf[3]) - 1); 3476 + skb_put_data(skb, &la.path.ru[4], sizeof(la.path.ru[4])); 3477 + skb_put_data(skb, &la.path.ru_bf[4][1], sizeof(la.path.ru_bf[4]) - 1); 3478 + 3479 + /* start from non-bf and bf fields of 3480 + * BW20/RU242, BW40/RU484, BW80/RU996, BW160/RU2x996, 3481 + * RU26, RU52, and RU106 3482 + */ 3483 + 3484 + for (i = 0; i < 8; i++) { 3485 + bool bf = i % 2; 3486 + u8 idx = (i + 6) / 2; 3487 + s8 *buf = bf ? la.path.ru_bf[idx] : la.path.ru[idx]; 3488 + /* The non-bf fields of RU26 to RU106 are special cases */ 3489 + if (bf) 3490 + skb_put_data(skb, buf + 1, 9); 3491 + else 3492 + skb_put_data(skb, buf, 10); 3493 + } 3494 + 3495 + for (i = 0; i < 6; i++) { 3496 + bool bf = i % 2; 3497 + u8 idx = i / 2; 3498 + s8 *buf = bf ? la.path.ru_bf[idx] : la.path.ru[idx]; 3499 + 3500 + skb_put_data(skb, buf, 10); 3501 + } 3502 + 3503 + return mt76_mcu_skb_send_msg(&dev->mt76, skb, 3504 + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), true); 3422 3505 } 3423 3506 3424 - int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len) 3507 + int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len, 3508 + u8 category) 3425 3509 { 3426 3510 #define RATE_POWER_INFO 2 3427 3511 struct mt7915_dev *dev = phy->dev; ··· 3517 3431 u8 _rsv; 3518 3432 } __packed req = { 3519 3433 .format_id = TX_POWER_LIMIT_INFO, 3520 - .category = RATE_POWER_INFO, 3434 + .category = category, 3521 3435 .band_idx = phy->mt76->band_idx, 3522 3436 }; 3523 - s8 txpower_sku[MT7915_SKU_RATE_NUM][2]; 3524 3437 struct sk_buff *skb; 3525 3438 int ret, i; 3526 3439 ··· 3529 3444 if (ret) 3530 3445 return ret; 3531 3446 3532 - memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku)); 3533 - for (i = 0; i < len; i++) 3534 - txpower[i] = txpower_sku[i][req.band_idx]; 3447 + if (category == TX_POWER_INFO_RATE) { 3448 + s8 res[MT7915_SKU_RATE_NUM][2]; 3449 + 3450 + memcpy(res, skb->data + 4, sizeof(res)); 3451 + for (i = 0; i < len; i++) 3452 + txpower[i] = res[i][req.band_idx]; 3453 + } else if (category == TX_POWER_INFO_PATH) { 3454 + memcpy(txpower, skb->data + 4, len); 3455 + } 3535 3456 3536 3457 dev_kfree_skb(skb); 3537 3458 ··· 3566 3475 sizeof(req), false); 3567 3476 } 3568 3477 3569 - int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) 3478 + int mt7915_mcu_set_sku_en(struct mt7915_phy *phy) 3570 3479 { 3571 3480 struct mt7915_dev *dev = phy->dev; 3572 3481 struct mt7915_sku { ··· 3575 3484 u8 band_idx; 3576 3485 u8 rsv; 3577 3486 } __packed req = { 3578 - .format_id = TX_POWER_LIMIT_ENABLE, 3579 3487 .band_idx = phy->mt76->band_idx, 3580 - .sku_enable = enable, 3581 3488 }; 3489 + int ret; 3490 + 3491 + req.sku_enable = phy->sku_limit_en; 3492 + req.format_id = TX_POWER_LIMIT_ENABLE; 3493 + 3494 + ret = mt76_mcu_send_msg(&dev->mt76, 3495 + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, 3496 + sizeof(req), true); 3497 + if (ret) 3498 + return ret; 3499 + 3500 + req.sku_enable = phy->sku_path_en; 3501 + req.format_id = TX_POWER_LIMIT_PATH_ENABLE; 3582 3502 3583 3503 return mt76_mcu_send_msg(&dev->mt76, 3584 3504 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
+7 -1
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7915_MCU_H ··· 429 429 430 430 enum { 431 431 TX_POWER_LIMIT_ENABLE, 432 + TX_POWER_LIMIT_PATH_ENABLE = 0x3, 432 433 TX_POWER_LIMIT_TABLE = 0x4, 433 434 TX_POWER_LIMIT_INFO = 0x7, 434 435 TX_POWER_LIMIT_FRAME = 0x11, 435 436 TX_POWER_LIMIT_FRAME_MIN = 0x12, 437 + }; 438 + 439 + enum { 440 + TX_POWER_INFO_PATH = 1, 441 + TX_POWER_INFO_RATE, 436 442 }; 437 443 438 444 enum {
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/kernel.h>
+8 -3
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7915_H ··· 70 70 #define MT7915_CDEV_THROTTLE_MAX 99 71 71 72 72 #define MT7915_SKU_RATE_NUM 161 73 + #define MT7915_SKU_PATH_NUM 185 73 74 74 75 #define MT7915_MAX_TWT_AGRT 16 75 76 #define MT7915_MAX_STA_TWT_AGRT 8 ··· 223 222 224 223 struct mt76_mib_stats mib; 225 224 struct mt76_channel_state state_ts; 225 + 226 + bool sku_limit_en:1; 227 + bool sku_path_en:1; 226 228 227 229 #ifdef CONFIG_NL80211_TESTMODE 228 230 struct { ··· 495 491 int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, 496 492 u8 en); 497 493 int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); 498 - int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable); 494 + int mt7915_mcu_set_sku_en(struct mt7915_phy *phy); 499 495 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy); 500 - int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len); 496 + int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len, 497 + u8 category); 501 498 int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower); 502 499 int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, 503 500 struct ieee80211_vif *vif,
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * Author: Ryder Lee <ryder.lee@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7915_REGS_H
+9 -14
drivers/net/wireless/mediatek/mt76/mt7915/soc.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2022 MediaTek Inc. */ 3 3 4 4 #include <linux/kernel.h> ··· 284 284 static int mt798x_wmac_coninfra_setup(struct mt7915_dev *dev) 285 285 { 286 286 struct device *pdev = dev->mt76.dev; 287 - struct reserved_mem *rmem; 288 - struct device_node *np; 287 + struct resource res; 289 288 u32 val; 289 + int ret; 290 290 291 - np = of_parse_phandle(pdev->of_node, "memory-region", 0); 292 - if (!np) 293 - return -EINVAL; 291 + ret = of_reserved_mem_region_to_resource(pdev->of_node, 0, &res); 292 + if (ret) 293 + return ret; 294 294 295 - rmem = of_reserved_mem_lookup(np); 296 - of_node_put(np); 297 - if (!rmem) 298 - return -EINVAL; 299 - 300 - val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK; 295 + val = (res.start >> 16) & MT_TOP_MCU_EMI_BASE_MASK; 301 296 302 297 if (is_mt7986(&dev->mt76)) { 303 298 /* Set conninfra subsys PLL check */ ··· 313 318 MT_TOP_EFUSE_BASE_MASK, 0x11f20000 >> 16); 314 319 } 315 320 316 - mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base); 317 - mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size); 321 + mt76_wr(dev, MT_INFRA_BUS_EMI_START, res.start); 322 + mt76_wr(dev, MT_INFRA_BUS_EMI_END, resource_size(&res)); 318 323 319 324 mt76_rr(dev, MT_CONN_INFRA_EFUSE); 320 325
+2 -2
drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include "mt7915.h" ··· 409 409 if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 410 410 return; 411 411 412 - mt7915_mcu_set_sku_en(phy, !en); 412 + mt7915_mcu_set_sku_en(phy); 413 413 414 414 mt7915_tm_mode_ctrl(dev, en); 415 415 mt7915_tm_reg_backup_restore(phy);
+1 -1
drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7915_TESTMODE_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/Kconfig
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT7921_COMMON 3 3 tristate 4 4 select MT792x_LIB
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/Makefile
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 obj-$(CONFIG_MT7921_COMMON) += mt7921-common.o 4 4 obj-$(CONFIG_MT7921E) += mt7921e.o
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include "mt7921.h"
+2 -2
drivers/net/wireless/mediatek/mt76/mt7921/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h> ··· 343 343 dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; 344 344 dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; 345 345 346 - queue_work(system_wq, &dev->init_work); 346 + queue_work(system_percpu_wq, &dev->init_work); 347 347 348 348 return 0; 349 349 }
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/devcoredump.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h>
+2 -2
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #include <linux/fs.h> ··· 646 646 if (err) 647 647 return err; 648 648 649 - set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 650 649 err = mt7921_load_clc(dev, mt792x_ram_name(dev)); 651 650 if (err) 652 651 return err; 652 + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 653 653 654 654 return mt7921_mcu_fw_log_2_host(dev, 1); 655 655 }
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7921_MCU_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7921_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2021 MediaTek Inc. */ 3 3 4 4 #include "mt7921.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2021 MediaTek Inc. */ 3 3 4 4 #include "mt7921.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7921_REGS_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2021 MediaTek Inc. 3 3 * 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2021 MediaTek Inc. */ 3 3 4 4 #include <linux/iopoll.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2021 MediaTek Inc. */ 3 3 4 4 #include <linux/kernel.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/testmode.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7921.h" 4 4 #include "mcu.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7921/usb.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2022 MediaTek Inc. 3 3 * 4 4 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/Kconfig
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT7925_COMMON 3 3 tristate 4 4 select MT792x_LIB
+2 -2
drivers/net/wireless/mediatek/mt76/mt7925/Makefile
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o 4 4 obj-$(CONFIG_MT7925E) += mt7925e.o 5 5 obj-$(CONFIG_MT7925U) += mt7925u.o 6 6 7 - mt7925-common-y := mac.o mcu.o main.o init.o debugfs.o 7 + mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o 8 8 mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o 9 9 mt7925e-y := pci.o pci_mac.o pci_mcu.o 10 10 mt7925u-y := usb.o
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include "mt7925.h"
+3 -149
drivers/net/wireless/mediatek/mt76/mt7925/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h> ··· 7 7 #include <linux/thermal.h> 8 8 #include <linux/firmware.h> 9 9 #include "mt7925.h" 10 + #include "regd.h" 10 11 #include "mac.h" 11 12 #include "mcu.h" 12 13 ··· 61 60 return PTR_ERR_OR_ZERO(hwmon); 62 61 } 63 62 64 - void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2) 65 - { 66 - struct mt792x_phy *phy = &dev->phy; 67 - struct mt7925_clc_rule_v2 *rule; 68 - struct mt7925_clc *clc; 69 - bool old = dev->has_eht, new = true; 70 - u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2); 71 - u8 *pos; 72 - 73 - if (mtcl_conf != MT792X_ACPI_MTCL_INVALID && 74 - (((mtcl_conf >> 4) & 0x3) == 0)) { 75 - new = false; 76 - goto out; 77 - } 78 - 79 - if (!phy->clc[MT792x_CLC_BE_CTRL]) 80 - goto out; 81 - 82 - clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL]; 83 - pos = clc->data; 84 - 85 - while (1) { 86 - rule = (struct mt7925_clc_rule_v2 *)pos; 87 - 88 - if (rule->alpha2[0] == alpha2[0] && 89 - rule->alpha2[1] == alpha2[1]) { 90 - new = false; 91 - break; 92 - } 93 - 94 - /* Check the last one */ 95 - if (rule->flag & BIT(0)) 96 - break; 97 - 98 - pos += sizeof(*rule); 99 - } 100 - 101 - out: 102 - if (old == new) 103 - return; 104 - 105 - dev->has_eht = new; 106 - mt7925_set_stream_he_eht_caps(phy); 107 - } 108 - 109 - static void 110 - mt7925_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) 111 - { 112 - #define IS_UNII_INVALID(idx, sfreq, efreq, cfreq) \ 113 - (!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq)) 114 - #define MT7925_UNII_59G_IS_VALID 0x1 115 - #define MT7925_UNII_6G_IS_VALID 0x1e 116 - struct ieee80211_supported_band *sband; 117 - struct mt76_dev *mdev = &dev->mt76; 118 - struct ieee80211_channel *ch; 119 - u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, mdev->alpha2); 120 - int i; 121 - 122 - if (mtcl_conf != MT792X_ACPI_MTCL_INVALID) { 123 - if ((mtcl_conf & 0x3) == 0) 124 - dev->phy.clc_chan_conf &= ~MT7925_UNII_59G_IS_VALID; 125 - if (((mtcl_conf >> 2) & 0x3) == 0) 126 - dev->phy.clc_chan_conf &= ~MT7925_UNII_6G_IS_VALID; 127 - } 128 - 129 - sband = wiphy->bands[NL80211_BAND_5GHZ]; 130 - if (!sband) 131 - return; 132 - 133 - for (i = 0; i < sband->n_channels; i++) { 134 - ch = &sband->channels[i]; 135 - 136 - /* UNII-4 */ 137 - if (IS_UNII_INVALID(0, 5845, 5925, ch->center_freq)) 138 - ch->flags |= IEEE80211_CHAN_DISABLED; 139 - } 140 - 141 - sband = wiphy->bands[NL80211_BAND_6GHZ]; 142 - if (!sband) 143 - return; 144 - 145 - for (i = 0; i < sband->n_channels; i++) { 146 - ch = &sband->channels[i]; 147 - 148 - /* UNII-5/6/7/8 */ 149 - if (IS_UNII_INVALID(1, 5925, 6425, ch->center_freq) || 150 - IS_UNII_INVALID(2, 6425, 6525, ch->center_freq) || 151 - IS_UNII_INVALID(3, 6525, 6875, ch->center_freq) || 152 - IS_UNII_INVALID(4, 6875, 7125, ch->center_freq)) 153 - ch->flags |= IEEE80211_CHAN_DISABLED; 154 - } 155 - } 156 - 157 - void mt7925_regd_update(struct mt792x_dev *dev) 158 - { 159 - struct mt76_dev *mdev = &dev->mt76; 160 - struct ieee80211_hw *hw = mdev->hw; 161 - struct wiphy *wiphy = hw->wiphy; 162 - 163 - if (!dev->regd_change) 164 - return; 165 - 166 - mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env); 167 - mt7925_regd_channel_update(wiphy, dev); 168 - mt7925_mcu_set_channel_domain(hw->priv); 169 - mt7925_set_tx_sar_pwr(hw, NULL); 170 - dev->regd_change = false; 171 - } 172 - EXPORT_SYMBOL_GPL(mt7925_regd_update); 173 - 174 - static void 175 - mt7925_regd_notifier(struct wiphy *wiphy, 176 - struct regulatory_request *req) 177 - { 178 - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 179 - struct mt792x_dev *dev = mt792x_hw_dev(hw); 180 - struct mt76_dev *mdev = &dev->mt76; 181 - struct mt76_connac_pm *pm = &dev->pm; 182 - 183 - /* allow world regdom at the first boot only */ 184 - if (!memcmp(req->alpha2, "00", 2) && 185 - mdev->alpha2[0] && mdev->alpha2[1]) 186 - return; 187 - 188 - /* do not need to update the same country twice */ 189 - if (!memcmp(req->alpha2, mdev->alpha2, 2) && 190 - dev->country_ie_env == req->country_ie_env) 191 - return; 192 - 193 - memcpy(mdev->alpha2, req->alpha2, 2); 194 - mdev->region = req->dfs_region; 195 - dev->country_ie_env = req->country_ie_env; 196 - dev->regd_change = true; 197 - 198 - if (pm->suspended) 199 - return; 200 - 201 - dev->regd_in_progress = true; 202 - mt792x_mutex_acquire(dev); 203 - mt7925_regd_update(dev); 204 - mt792x_mutex_release(dev); 205 - dev->regd_in_progress = false; 206 - wake_up(&dev->wait); 207 - } 208 - 209 63 static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev) 210 64 { 211 65 int i; ··· 90 234 mt792x_mac_init_band(dev, i); 91 235 92 236 mt7925_mac_init_basic_rates(dev); 93 - 94 - memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2)); 95 237 96 238 return 0; 97 239 } ··· 274 420 dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; 275 421 dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; 276 422 277 - queue_work(system_wq, &dev->init_work); 423 + queue_work(system_percpu_wq, &dev->init_work); 278 424 279 425 return 0; 280 426 }
+3 -4
drivers/net/wireless/mediatek/mt76/mt7925/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/devcoredump.h> ··· 6 6 #include <linux/timekeeping.h> 7 7 #include "mt7925.h" 8 8 #include "../dma.h" 9 + #include "regd.h" 9 10 #include "mac.h" 10 11 #include "mcu.h" 11 12 ··· 1330 1329 mt7925_vif_connect_iter, NULL); 1331 1330 mt76_connac_power_save_sched(&dev->mt76.phy, pm); 1332 1331 1333 - mt792x_mutex_acquire(dev); 1334 - mt7925_mcu_set_clc(dev, "00", ENVIRON_INDOOR); 1335 - mt792x_mutex_release(dev); 1332 + mt7925_regd_change(&dev->phy, "00"); 1336 1333 } 1337 1334 1338 1335 void mt7925_coredump_work(struct work_struct *work)
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7925_MAC_H
+14 -26
drivers/net/wireless/mediatek/mt76/mt7925/main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/etherdevice.h> ··· 8 8 #include <linux/ctype.h> 9 9 #include <net/ipv6.h> 10 10 #include "mt7925.h" 11 + #include "regd.h" 11 12 #include "mcu.h" 12 13 #include "mac.h" 13 14 ··· 139 138 } 140 139 141 140 if (band == NL80211_BAND_6GHZ) { 141 + struct ieee80211_supported_band *sband = 142 + &phy->mt76->sband_5g.sband; 143 + struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; 144 + 142 145 u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | 143 146 IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; 144 147 145 - cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5, 148 + cap |= u16_encode_bits(ht_cap->ampdu_density, 146 149 IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | 147 150 u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, 148 151 IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | ··· 435 430 goto out; 436 431 437 432 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; 433 + if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN) 434 + vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI; 435 + 438 436 out: 439 437 mt792x_mutex_release(dev); 440 438 ··· 1320 1312 mt7925_mlo_pm_iter, dev); 1321 1313 } 1322 1314 1323 - static bool is_valid_alpha2(const char *alpha2) 1324 - { 1325 - if (!alpha2) 1326 - return false; 1327 - 1328 - if (alpha2[0] == '0' && alpha2[1] == '0') 1329 - return true; 1330 - 1331 - if (isalpha(alpha2[0]) && isalpha(alpha2[1])) 1332 - return true; 1333 - 1334 - return false; 1335 - } 1336 - 1337 1315 void mt7925_scan_work(struct work_struct *work) 1338 1316 { 1339 1317 struct mt792x_phy *phy; ··· 1328 1334 scan_work.work); 1329 1335 1330 1336 while (true) { 1331 - struct mt76_dev *mdev = &phy->dev->mt76; 1332 1337 struct sk_buff *skb; 1333 1338 struct tlv *tlv; 1334 1339 int tlv_len; ··· 1358 1365 case UNI_EVENT_SCAN_DONE_CHNLINFO: 1359 1366 evt = (struct mt7925_mcu_scan_chinfo_event *)tlv->data; 1360 1367 1361 - if (!is_valid_alpha2(evt->alpha2)) 1362 - break; 1363 - 1364 - mt7925_regd_be_ctrl(phy->dev, evt->alpha2); 1365 - 1366 - if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0') 1367 - break; 1368 - 1369 - mt7925_mcu_set_clc(phy->dev, evt->alpha2, ENVIRON_INDOOR); 1368 + mt7925_regd_change(phy, evt->alpha2); 1370 1369 1371 1370 break; 1372 1371 case UNI_EVENT_SCAN_DONE_NLO: ··· 1942 1957 if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING) 1943 1958 mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76, 1944 1959 link_conf, NULL); 1960 + 1961 + if (changed & BSS_CHANGED_CQM) 1962 + mt7925_mcu_set_rssimonitor(dev, vif); 1945 1963 1946 1964 mt792x_mutex_release(dev); 1947 1965 }
+91 -8
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/fs.h> 5 5 #include <linux/firmware.h> 6 6 #include "mt7925.h" 7 + #include "regd.h" 7 8 #include "mcu.h" 8 9 #include "mac.h" 9 10 10 11 #define MT_STA_BFER BIT(0) 11 12 #define MT_STA_BFEE BIT(1) 12 - 13 - static bool mt7925_disable_clc; 14 - module_param_named(disable_clc, mt7925_disable_clc, bool, 0644); 15 - MODULE_PARM_DESC(disable_clc, "disable CLC support"); 16 13 17 14 int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd, 18 15 struct sk_buff *skb, int seq) ··· 448 451 } 449 452 450 453 static void 454 + mt7925_mcu_rssi_monitor_iter(void *priv, u8 *mac, 455 + struct ieee80211_vif *vif) 456 + { 457 + struct mt7925_uni_rssi_monitor_event *event = priv; 458 + enum nl80211_cqm_rssi_threshold_event nl_event; 459 + s32 rssi = le32_to_cpu(event->rssi); 460 + 461 + if (vif->type != NL80211_IFTYPE_STATION) 462 + return; 463 + 464 + if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) 465 + return; 466 + 467 + if (rssi > vif->bss_conf.cqm_rssi_thold) 468 + nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; 469 + else 470 + nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; 471 + 472 + ieee80211_cqm_rssi_notify(vif, nl_event, rssi, GFP_KERNEL); 473 + } 474 + 475 + static void 476 + mt7925_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb) 477 + { 478 + struct tlv *tlv; 479 + u32 tlv_len; 480 + struct mt7925_uni_rssi_monitor_event *event; 481 + 482 + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); 483 + tlv = (struct tlv *)skb->data; 484 + tlv_len = skb->len; 485 + 486 + while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) { 487 + switch (le16_to_cpu(tlv->tag)) { 488 + case UNI_EVENT_RSSI_MONITOR_INFO: 489 + event = (struct mt7925_uni_rssi_monitor_event *)skb->data; 490 + ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, 491 + IEEE80211_IFACE_ITER_RESUME_ALL, 492 + mt7925_mcu_rssi_monitor_iter, 493 + event); 494 + break; 495 + default: 496 + break; 497 + } 498 + tlv_len -= le16_to_cpu(tlv->len); 499 + tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len)); 500 + } 501 + } 502 + 503 + static void 451 504 mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) 452 505 { 453 506 struct mt7925_uni_debug_msg { ··· 592 545 break; 593 546 case MCU_UNI_EVENT_BSS_BEACON_LOSS: 594 547 mt7925_mcu_connection_loss_event(dev, skb); 548 + break; 549 + case MCU_UNI_EVENT_RSSI_MONITOR: 550 + mt7925_mcu_rssi_monitor_event(dev, skb); 595 551 break; 596 552 case MCU_UNI_EVENT_COREDUMP: 597 553 dev->fw_assert = true; ··· 738 688 int ret, i, len, offset = 0; 739 689 740 690 dev->phy.clc_chan_conf = 0xff; 741 - if (mt7925_disable_clc || 742 - mt76_is_usb(&dev->mt76)) 691 + dev->regd_user = false; 692 + if (!mt7925_regd_clc_supported(dev)) 743 693 return 0; 744 694 745 695 if (mt76_is_mmio(&dev->mt76)) { ··· 809 759 } 810 760 } 811 761 762 + ret = mt7925_regd_init(phy); 812 763 out: 813 764 release_firmware(fw); 814 765 ··· 1054 1003 if (err) 1055 1004 return err; 1056 1005 1057 - set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 1058 1006 err = mt7925_load_clc(dev, mt792x_ram_name(dev)); 1059 1007 if (err) 1060 1008 return err; 1009 + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 1061 1010 1062 1011 return mt7925_mcu_fw_log_2_host(dev, 1); 1063 1012 } ··· 3434 3383 struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy; 3435 3384 int i, ret; 3436 3385 3386 + if (!ARRAY_SIZE(phy->clc)) 3387 + return -ESRCH; 3388 + 3437 3389 /* submit all clc config */ 3438 3390 for (i = 0; i < ARRAY_SIZE(phy->clc); i++) { 3439 3391 if (i == MT792x_CLC_BE_CTRL) ··· 3871 3817 3872 3818 return mt76_mcu_send_msg(&phy->dev->mt76, MCU_UNI_CMD(BAND_CONFIG), 3873 3819 &req, sizeof(req), true); 3820 + } 3821 + 3822 + int mt7925_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif) 3823 + { 3824 + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(&vif->bss_conf); 3825 + struct { 3826 + struct { 3827 + u8 bss_idx; 3828 + u8 pad[3]; 3829 + } __packed hdr; 3830 + __le16 tag; 3831 + __le16 len; 3832 + u8 enable; 3833 + s8 cqm_rssi_high; 3834 + s8 cqm_rssi_low; 3835 + u8 rsv; 3836 + } req = { 3837 + .hdr = { 3838 + .bss_idx = mconf->mt76.idx, 3839 + }, 3840 + .tag = cpu_to_le16(UNI_CMD_RSSI_MONITOR_SET), 3841 + .len = cpu_to_le16(sizeof(req) - 4), 3842 + .enable = vif->cfg.assoc, 3843 + .cqm_rssi_high = (s8)(vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst), 3844 + .cqm_rssi_low = (s8)(vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst), 3845 + }; 3846 + 3847 + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(RSSI_MONITOR), &req, 3848 + sizeof(req), false); 3874 3849 }
+9 -1
drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7925_MCU_H ··· 150 150 UNI_EVENT_SCAN_DONE_BASIC = 0, 151 151 UNI_EVENT_SCAN_DONE_CHNLINFO = 2, 152 152 UNI_EVENT_SCAN_DONE_NLO = 3, 153 + }; 154 + 155 + enum { 156 + UNI_CMD_RSSI_MONITOR_SET = 0, 157 + }; 158 + 159 + enum { 160 + UNI_EVENT_RSSI_MONITOR_INFO = 0, 153 161 }; 154 162 155 163 enum connac3_mcu_cipher_type {
+8 -3
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7925_H ··· 101 101 u8 pad[3]; 102 102 } __packed hdr; 103 103 struct mt7925_beacon_loss_tlv beacon_loss; 104 + } __packed; 105 + 106 + struct mt7925_uni_rssi_monitor_event { 107 + __le16 tag; 108 + __le16 len; 109 + __le32 rssi; 104 110 } __packed; 105 111 106 112 #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) ··· 263 257 int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, 264 258 u8 bit_op, u32 bit_map); 265 259 266 - void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2); 267 - void mt7925_regd_update(struct mt792x_dev *dev); 268 260 int mt7925_mac_init(struct mt792x_dev *dev); 269 261 int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, 270 262 struct ieee80211_sta *sta); ··· 376 372 int mt7925_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, 377 373 struct netlink_callback *cb, void *data, int len); 378 374 375 + int mt7925_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif); 379 376 #endif
+3 -2
drivers/net/wireless/mediatek/mt76/mt7925/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/kernel.h> ··· 8 8 #include "mt7925.h" 9 9 #include "mac.h" 10 10 #include "mcu.h" 11 + #include "regd.h" 11 12 #include "../dma.h" 12 13 13 14 static const struct pci_device_id mt7925_pci_device_table[] = { ··· 585 584 if (!pm->ds_enable) 586 585 mt7925_mcu_set_deep_sleep(dev, false); 587 586 588 - mt7925_regd_update(dev); 587 + mt7925_mcu_regd_update(dev, mdev->alpha2, dev->country_ie_env); 589 588 failed: 590 589 pm->suspended = false; 591 590
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include "mt7925.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include "mt7925.h"
+265
drivers/net/wireless/mediatek/mt76/mt7925/regd.c
··· 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 + /* Copyright (C) 2025 MediaTek Inc. */ 3 + 4 + #include "mt7925.h" 5 + #include "regd.h" 6 + #include "mcu.h" 7 + 8 + static bool mt7925_disable_clc; 9 + module_param_named(disable_clc, mt7925_disable_clc, bool, 0644); 10 + MODULE_PARM_DESC(disable_clc, "disable CLC support"); 11 + 12 + bool mt7925_regd_clc_supported(struct mt792x_dev *dev) 13 + { 14 + if (mt7925_disable_clc || 15 + mt76_is_usb(&dev->mt76)) 16 + return false; 17 + 18 + return true; 19 + } 20 + 21 + void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2) 22 + { 23 + struct mt792x_phy *phy = &dev->phy; 24 + struct mt7925_clc_rule_v2 *rule; 25 + struct mt7925_clc *clc; 26 + bool old = dev->has_eht, new = true; 27 + u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2); 28 + u8 *pos; 29 + 30 + if (mtcl_conf != MT792X_ACPI_MTCL_INVALID && 31 + (((mtcl_conf >> 4) & 0x3) == 0)) { 32 + new = false; 33 + goto out; 34 + } 35 + 36 + if (!phy->clc[MT792x_CLC_BE_CTRL]) 37 + goto out; 38 + 39 + clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL]; 40 + pos = clc->data; 41 + 42 + while (1) { 43 + rule = (struct mt7925_clc_rule_v2 *)pos; 44 + 45 + if (rule->alpha2[0] == alpha2[0] && 46 + rule->alpha2[1] == alpha2[1]) { 47 + new = false; 48 + break; 49 + } 50 + 51 + /* Check the last one */ 52 + if (rule->flag & BIT(0)) 53 + break; 54 + 55 + pos += sizeof(*rule); 56 + } 57 + 58 + out: 59 + if (old == new) 60 + return; 61 + 62 + dev->has_eht = new; 63 + mt7925_set_stream_he_eht_caps(phy); 64 + } 65 + 66 + static void 67 + mt7925_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) 68 + { 69 + #define IS_UNII_INVALID(idx, sfreq, efreq, cfreq) \ 70 + (!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq)) 71 + #define MT7925_UNII_59G_IS_VALID 0x1 72 + #define MT7925_UNII_6G_IS_VALID 0x1e 73 + struct ieee80211_supported_band *sband; 74 + struct mt76_dev *mdev = &dev->mt76; 75 + struct ieee80211_channel *ch; 76 + u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, mdev->alpha2); 77 + int i; 78 + 79 + if (mtcl_conf != MT792X_ACPI_MTCL_INVALID) { 80 + if ((mtcl_conf & 0x3) == 0) 81 + dev->phy.clc_chan_conf &= ~MT7925_UNII_59G_IS_VALID; 82 + if (((mtcl_conf >> 2) & 0x3) == 0) 83 + dev->phy.clc_chan_conf &= ~MT7925_UNII_6G_IS_VALID; 84 + } 85 + 86 + sband = wiphy->bands[NL80211_BAND_2GHZ]; 87 + if (!sband) 88 + return; 89 + 90 + for (i = 0; i < sband->n_channels; i++) { 91 + ch = &sband->channels[i]; 92 + 93 + if (!dev->has_eht) 94 + ch->flags |= IEEE80211_CHAN_NO_EHT; 95 + } 96 + 97 + sband = wiphy->bands[NL80211_BAND_5GHZ]; 98 + if (!sband) 99 + return; 100 + 101 + for (i = 0; i < sband->n_channels; i++) { 102 + ch = &sband->channels[i]; 103 + 104 + /* UNII-4 */ 105 + if (IS_UNII_INVALID(0, 5845, 5925, ch->center_freq)) 106 + ch->flags |= IEEE80211_CHAN_DISABLED; 107 + 108 + if (!dev->has_eht) 109 + ch->flags |= IEEE80211_CHAN_NO_EHT; 110 + } 111 + 112 + sband = wiphy->bands[NL80211_BAND_6GHZ]; 113 + if (!sband) 114 + return; 115 + 116 + for (i = 0; i < sband->n_channels; i++) { 117 + ch = &sband->channels[i]; 118 + 119 + /* UNII-5/6/7/8 */ 120 + if (IS_UNII_INVALID(1, 5925, 6425, ch->center_freq) || 121 + IS_UNII_INVALID(2, 6425, 6525, ch->center_freq) || 122 + IS_UNII_INVALID(3, 6525, 6875, ch->center_freq) || 123 + IS_UNII_INVALID(4, 6875, 7125, ch->center_freq)) 124 + ch->flags |= IEEE80211_CHAN_DISABLED; 125 + 126 + if (!dev->has_eht) 127 + ch->flags |= IEEE80211_CHAN_NO_EHT; 128 + } 129 + } 130 + 131 + int mt7925_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2, 132 + enum environment_cap country_ie_env) 133 + { 134 + struct ieee80211_hw *hw = mt76_hw(dev); 135 + struct wiphy *wiphy = hw->wiphy; 136 + int ret = 0; 137 + 138 + dev->regd_in_progress = true; 139 + 140 + mt792x_mutex_acquire(dev); 141 + if (!dev->regd_change) 142 + goto err; 143 + 144 + ret = mt7925_mcu_set_clc(dev, alpha2, country_ie_env); 145 + if (ret < 0) 146 + goto err; 147 + 148 + mt7925_regd_be_ctrl(dev, alpha2); 149 + mt7925_regd_channel_update(wiphy, dev); 150 + 151 + ret = mt7925_mcu_set_channel_domain(hw->priv); 152 + if (ret < 0) 153 + goto err; 154 + 155 + ret = mt7925_set_tx_sar_pwr(hw, NULL); 156 + if (ret < 0) 157 + goto err; 158 + 159 + err: 160 + mt792x_mutex_release(dev); 161 + dev->regd_change = false; 162 + dev->regd_in_progress = false; 163 + wake_up(&dev->wait); 164 + 165 + return ret; 166 + } 167 + EXPORT_SYMBOL_GPL(mt7925_mcu_regd_update); 168 + 169 + void mt7925_regd_notifier(struct wiphy *wiphy, struct regulatory_request *req) 170 + { 171 + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 172 + struct mt792x_dev *dev = mt792x_hw_dev(hw); 173 + struct mt76_connac_pm *pm = &dev->pm; 174 + struct mt76_dev *mdev = &dev->mt76; 175 + 176 + if (req->initiator == NL80211_REGDOM_SET_BY_USER && 177 + !dev->regd_user) 178 + dev->regd_user = true; 179 + 180 + /* allow world regdom at the first boot only */ 181 + if (!memcmp(req->alpha2, "00", 2) && 182 + mdev->alpha2[0] && mdev->alpha2[1]) 183 + return; 184 + 185 + /* do not need to update the same country twice */ 186 + if (!memcmp(req->alpha2, mdev->alpha2, 2) && 187 + dev->country_ie_env == req->country_ie_env) 188 + return; 189 + 190 + memcpy(mdev->alpha2, req->alpha2, 2); 191 + mdev->region = req->dfs_region; 192 + dev->country_ie_env = req->country_ie_env; 193 + 194 + dev->regd_change = true; 195 + 196 + if (pm->suspended) 197 + /* postpone the mcu update to resume */ 198 + return; 199 + 200 + mt7925_mcu_regd_update(dev, req->alpha2, 201 + req->country_ie_env); 202 + return; 203 + } 204 + 205 + static bool 206 + mt7925_regd_is_valid_alpha2(const char *alpha2) 207 + { 208 + if (!alpha2) 209 + return false; 210 + 211 + if (alpha2[0] == '0' && alpha2[1] == '0') 212 + return true; 213 + 214 + if (isalpha(alpha2[0]) && isalpha(alpha2[1])) 215 + return true; 216 + 217 + return false; 218 + } 219 + 220 + int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2) 221 + { 222 + struct wiphy *wiphy = phy->mt76->hw->wiphy; 223 + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 224 + struct mt792x_dev *dev = mt792x_hw_dev(hw); 225 + struct mt76_dev *mdev = &dev->mt76; 226 + 227 + if (dev->hw_full_reset) 228 + return 0; 229 + 230 + if (!mt7925_regd_is_valid_alpha2(alpha2) || 231 + !mt7925_regd_clc_supported(dev) || 232 + dev->regd_user) 233 + return -EINVAL; 234 + 235 + if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0') 236 + return 0; 237 + 238 + /* do not need to update the same country twice */ 239 + if (!memcmp(alpha2, mdev->alpha2, 2)) 240 + return 0; 241 + 242 + if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN) { 243 + return regulatory_hint(wiphy, alpha2); 244 + } else { 245 + return mt7925_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR); 246 + } 247 + } 248 + EXPORT_SYMBOL_GPL(mt7925_regd_change); 249 + 250 + int mt7925_regd_init(struct mt792x_phy *phy) 251 + { 252 + struct wiphy *wiphy = phy->mt76->hw->wiphy; 253 + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 254 + struct mt792x_dev *dev = mt792x_hw_dev(hw); 255 + struct mt76_dev *mdev = &dev->mt76; 256 + 257 + if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN) { 258 + wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE | 259 + REGULATORY_DISABLE_BEACON_HINTS; 260 + } else { 261 + memzero_explicit(&mdev->alpha2, sizeof(mdev->alpha2)); 262 + } 263 + 264 + return 0; 265 + }
+19
drivers/net/wireless/mediatek/mt76/mt7925/regd.h
··· 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 + /* Copyright (C) 2025 MediaTek Inc. */ 3 + 4 + #ifndef __MT7925_REGD_H 5 + #define __MT7925_REGD_H 6 + 7 + #include "mt7925.h" 8 + 9 + int mt7925_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2, 10 + enum environment_cap country_ie_env); 11 + 12 + void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2); 13 + void mt7925_regd_notifier(struct wiphy *wiphy, struct regulatory_request *req); 14 + bool mt7925_regd_clc_supported(struct mt792x_dev *dev); 15 + int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2); 16 + int mt7925_regd_init(struct mt792x_phy *phy); 17 + 18 + #endif 19 +
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7925_REGS_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/testmode.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 #include "mt7925.h" 4 4 #include "mcu.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt7925/usb.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/kernel.h>
+3 -1
drivers/net/wireless/mediatek/mt76/mt792x.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT792X_H ··· 28 28 #define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0) 29 29 #define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1) 30 30 #define MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN BIT(3) 31 + #define MT792x_CHIP_CAP_11D_EN BIT(4) 31 32 #define MT792x_CHIP_CAP_MLO_EN BIT(8) 32 33 #define MT792x_CHIP_CAP_MLO_EML_EN BIT(9) 33 34 ··· 231 230 bool hw_init_done:1; 232 231 bool fw_assert:1; 233 232 bool has_eht:1; 233 + bool regd_user:1; 234 234 bool regd_in_progress:1; 235 235 bool aspm_supported:1; 236 236 bool hif_idle:1;
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/acpi.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT7921_ACPI_SAR_H
+1 -2
drivers/net/wireless/mediatek/mt76/mt792x_core.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/module.h> ··· 688 688 ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); 689 689 ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); 690 690 ieee80211_hw_set(hw, CONNECTION_MONITOR); 691 - ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR); 692 691 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); 693 692 ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID); 694 693
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include "mt792x.h"
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_dma.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/module.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/module.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef __MT792X_REGS_H
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_trace.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_trace.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt792x_usb.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. 3 3 * 4 4 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
+8 -1
drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 config MT7996E 3 3 tristate "MediaTek MT7996 (PCIe) support" 4 4 select MT76_CONNAC_LIB ··· 12 12 and 2.4GHz IEEE 802.11be 4x4:4SS 4096-QAM, 320MHz channels. 13 13 14 14 To compile this driver as a module, choose M here. 15 + 16 + config MT7996_NPU 17 + bool "MT7996 (PCIe) NPU support" 18 + depends on MT7996E 19 + depends on NET_AIROHA_NPU=y || MT7996E=NET_AIROHA_NPU 20 + select MT76_NPU 21 + default n
+2 -1
drivers/net/wireless/mediatek/mt76/mt7996/Makefile
··· 1 - # SPDX-License-Identifier: ISC 1 + # SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 3 3 obj-$(CONFIG_MT7996E) += mt7996e.o 4 4 5 5 mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ 6 6 debugfs.o mmio.o 7 7 8 + mt7996e-$(CONFIG_MT7996_NPU) += npu.o 8 9 mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/coredump.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #include <linux/devcoredump.h>
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/coredump.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 3 4 4 #ifndef _COREDUMP_H_
+45 -29
drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 953 953 #ifdef CONFIG_MAC80211_DEBUGFS 954 954 /** per-station debugfs **/ 955 955 956 - static ssize_t mt7996_sta_fixed_rate_set(struct file *file, 957 - const char __user *user_buf, 958 - size_t count, loff_t *ppos) 956 + static int 957 + mt7996_queues_show(struct seq_file *s, void *data) 958 + { 959 + struct ieee80211_sta *sta = s->private; 960 + 961 + mt7996_sta_hw_queue_read(s, sta); 962 + 963 + return 0; 964 + } 965 + 966 + DEFINE_SHOW_ATTRIBUTE(mt7996_queues); 967 + 968 + void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 969 + struct ieee80211_sta *sta, struct dentry *dir) 970 + { 971 + debugfs_create_file("hw-queues", 0400, dir, sta, &mt7996_queues_fops); 972 + } 973 + 974 + static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file, 975 + const char __user *user_buf, 976 + size_t count, loff_t *ppos) 959 977 { 960 978 #define SHORT_PREAMBLE 0 961 979 #define LONG_PREAMBLE 1 962 - struct ieee80211_sta *sta = file->private_data; 963 - struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 980 + struct ieee80211_link_sta *link_sta = file->private_data; 981 + struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv; 964 982 struct mt7996_dev *dev = msta->vif->deflink.phy->dev; 965 - struct mt7996_sta_link *msta_link = &msta->deflink; 983 + struct mt7996_sta_link *msta_link; 966 984 struct ra_rate phy = {}; 967 985 char buf[100]; 968 986 int ret; ··· 999 981 1000 982 /* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9 EHT: 15 1001 983 * bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3, BW320: 4 1002 - * nss - vht: 1~4, he: 1~4, eht: 1~4, others: ignore 1003 984 * mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2, eht: 0~13 985 + * nss - vht: 1~4, he: 1~4, eht: 1~4, others: ignore 1004 986 * gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2 1005 987 * preamble - short: 1, long: 0 1006 - * ldpc - off: 0, on: 1 1007 988 * stbc - off: 0, on: 1 989 + * ldpc - off: 0, on: 1 990 + * spe - off: 0, on: 1 1008 991 * ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2 1009 992 */ 1010 993 if (sscanf(buf, "%hhu %hhu %hhu %hhu %hu %hhu %hhu %hhu %hhu %hu", ··· 1013 994 &phy.preamble, &phy.stbc, &phy.ldpc, &phy.spe, &ltf) != 10) { 1014 995 dev_warn(dev->mt76.dev, 1015 996 "format: Mode BW MCS NSS GI Preamble STBC LDPC SPE ltf\n"); 1016 - goto out; 997 + return -EINVAL; 1017 998 } 1018 999 1000 + mutex_lock(&dev->mt76.mutex); 1001 + 1002 + msta_link = mt76_dereference(msta->link[link_sta->link_id], &dev->mt76); 1003 + if (!msta_link) { 1004 + ret = -EINVAL; 1005 + goto out; 1006 + } 1019 1007 phy.wlan_idx = cpu_to_le16(msta_link->wcid.idx); 1020 1008 phy.gi = cpu_to_le16(gi); 1021 1009 phy.ltf = cpu_to_le16(ltf); ··· 1031 1005 1032 1006 ret = mt7996_mcu_set_fixed_rate_ctrl(dev, &phy, 0); 1033 1007 if (ret) 1034 - return -EFAULT; 1008 + goto out; 1035 1009 1010 + ret = count; 1036 1011 out: 1037 - return count; 1012 + mutex_unlock(&dev->mt76.mutex); 1013 + return ret; 1038 1014 } 1039 1015 1040 1016 static const struct file_operations fops_fixed_rate = { 1041 - .write = mt7996_sta_fixed_rate_set, 1017 + .write = mt7996_link_sta_fixed_rate_set, 1042 1018 .open = simple_open, 1043 1019 .owner = THIS_MODULE, 1044 1020 .llseek = default_llseek, 1045 1021 }; 1046 1022 1047 - static int 1048 - mt7996_queues_show(struct seq_file *s, void *data) 1023 + void mt7996_link_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1024 + struct ieee80211_link_sta *link_sta, 1025 + struct dentry *dir) 1049 1026 { 1050 - struct ieee80211_sta *sta = s->private; 1051 - 1052 - mt7996_sta_hw_queue_read(s, sta); 1053 - 1054 - return 0; 1055 - } 1056 - 1057 - DEFINE_SHOW_ATTRIBUTE(mt7996_queues); 1058 - 1059 - void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1060 - struct ieee80211_sta *sta, struct dentry *dir) 1061 - { 1062 - debugfs_create_file("fixed_rate", 0600, dir, sta, &fops_fixed_rate); 1063 - debugfs_create_file("hw-queues", 0400, dir, sta, &mt7996_queues_fops); 1027 + debugfs_create_file("fixed_rate", 0600, dir, link_sta, &fops_fixed_rate); 1064 1028 } 1065 1029 1066 1030 #endif
+23 -10
drivers/net/wireless/mediatek/mt76/mt7996/dma.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 22 22 else 23 23 flags = MT_WED_Q_TX(idx); 24 24 } 25 + 26 + if (mt76_npu_device_active(&dev->mt76)) 27 + flags = MT_NPU_Q_TX(phy->mt76->band_idx); 25 28 26 29 return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, 27 30 ring_base, wed, flags); ··· 347 344 mtk_wed_device_start(wed, wed_irq_mask); 348 345 } 349 346 350 - if (!mt7996_has_wa(dev)) 347 + if (!mt7996_has_wa(dev) || mt76_npu_device_active(&dev->mt76)) 351 348 irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) | 352 349 MT_INT_RX(MT_RXQ_BAND1_WA)); 353 350 irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; ··· 505 502 mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].flags = MT_WED_RRO_Q_RXDMAD_C; 506 503 if (mtk_wed_device_active(&mdev->mmio.wed)) 507 504 mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].wed = &mdev->mmio.wed; 508 - else 505 + else if (!mt76_npu_device_active(&dev->mt76)) 509 506 mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].flags |= MT_QFLAG_EMI_EN; 510 507 ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C], 511 508 MT_RXQ_ID(MT_RXQ_RRO_RXDMAD_C), ··· 515 512 if (ret) 516 513 return ret; 517 514 518 - /* We need to set cpu idx pointer before resetting the EMI 519 - * queues. 520 - */ 521 - mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx = 522 - &dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx; 523 - mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C], true); 515 + if (!mtk_wed_device_active(&mdev->mmio.wed)) { 516 + /* We need to set cpu idx pointer before resetting the 517 + * EMI queues. 518 + */ 519 + mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx = 520 + &dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx; 521 + mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C], 522 + true); 523 + } 524 524 goto start_hw_rro; 525 525 } 526 526 ··· 616 610 mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0, 617 611 mt76_dma_rx_poll); 618 612 } 619 - mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE); 613 + 614 + if (!mt76_npu_device_active(&dev->mt76)) 615 + mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE); 620 616 } 621 617 622 618 return 0; ··· 892 884 if (ret < 0) 893 885 return ret; 894 886 887 + ret = mt7996_npu_rx_queues_init(dev); 888 + if (ret) 889 + return ret; 890 + 895 891 netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, 896 892 mt7996_poll_tx); 897 893 napi_enable(&dev->mt76.tx_napi); ··· 953 941 if (mtk_wed_device_active(&dev->mt76.mmio.wed)) 954 942 mtk_wed_device_dma_reset(&dev->mt76.mmio.wed); 955 943 944 + mt76_npu_disable_irqs(&dev->mt76); 956 945 mt7996_dma_disable(dev, force); 957 946 mt76_wed_dma_reset(&dev->mt76); 958 947
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */
+28 -6
drivers/net/wireless/mediatek/mt76/mt7996/init.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 475 475 hw->max_tx_aggregation_subframes = 512; 476 476 477 477 hw->netdev_features = NETIF_F_RXCSUM; 478 - if (mtk_wed_device_active(wed)) 478 + if (mtk_wed_device_active(wed) || mt76_npu_device_active(mdev)) 479 479 hw->netdev_features |= NETIF_F_HW_TC; 480 480 481 481 hw->radiotap_timestamp.units_pos = ··· 830 830 MT_RRO_3_0_EMU_CONF_EN_MASK); 831 831 mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG, 832 832 MT_RRO_3_1_GLOBAL_CONFIG_RXDMAD_SEL); 833 - if (!mtk_wed_device_active(&dev->mt76.mmio.wed)) { 833 + if (!mtk_wed_device_active(&dev->mt76.mmio.wed) && 834 + !mt76_npu_device_active(&dev->mt76)) { 834 835 mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG, 835 836 MT_RRO_3_1_GLOBAL_CONFIG_RX_DIDX_WR_EN | 836 837 MT_RRO_3_1_GLOBAL_CONFIG_RX_CIDX_RD_EN); ··· 960 959 MT7996_RRO_MSDU_PG_SIZE_PER_CR); 961 960 } 962 961 963 - if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) { 962 + if (!mtk_wed_device_active(&dev->mt76.mmio.wed) && 963 + dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) { 964 964 ptr = dmam_alloc_coherent(dev->mt76.dma_dev, 965 - sizeof(dev->wed_rro.emi_rings_cpu.ptr), 965 + sizeof(*dev->wed_rro.emi_rings_cpu.ptr), 966 966 &dev->wed_rro.emi_rings_cpu.phy_addr, 967 967 GFP_KERNEL); 968 968 if (!ptr) ··· 972 970 dev->wed_rro.emi_rings_cpu.ptr = ptr; 973 971 974 972 ptr = dmam_alloc_coherent(dev->mt76.dma_dev, 975 - sizeof(dev->wed_rro.emi_rings_dma.ptr), 973 + sizeof(*dev->wed_rro.emi_rings_dma.ptr), 976 974 &dev->wed_rro.emi_rings_dma.phy_addr, 977 975 GFP_KERNEL); 978 976 if (!ptr) ··· 1038 1036 dev->wed_rro.msdu_pg[i].phy_addr); 1039 1037 } 1040 1038 1039 + if (dev->wed_rro.emi_rings_cpu.ptr) 1040 + dmam_free_coherent(dev->mt76.dma_dev, 1041 + sizeof(*dev->wed_rro.emi_rings_cpu.ptr), 1042 + dev->wed_rro.emi_rings_cpu.ptr, 1043 + dev->wed_rro.emi_rings_cpu.phy_addr); 1044 + 1045 + if (dev->wed_rro.emi_rings_dma.ptr) 1046 + dmam_free_coherent(dev->mt76.dma_dev, 1047 + sizeof(*dev->wed_rro.emi_rings_dma.ptr), 1048 + dev->wed_rro.emi_rings_dma.ptr, 1049 + dev->wed_rro.emi_rings_dma.phy_addr); 1050 + 1041 1051 if (!dev->wed_rro.session.ptr) 1042 1052 return; 1043 1053 ··· 1081 1067 list); 1082 1068 list_del_init(&e->list); 1083 1069 1070 + if (mt76_npu_device_active(&dev->mt76)) 1071 + goto reset_session; 1072 + 1084 1073 for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) { 1085 1074 void *ptr = dev->wed_rro.session.ptr; 1086 1075 struct mt7996_wed_rro_addr *elem; ··· 1104 1087 elem = ptr + elem_id * sizeof(*elem); 1105 1088 elem->data |= cpu_to_le32(val); 1106 1089 } 1090 + reset_session: 1107 1091 mt7996_mcu_wed_rro_reset_sessions(dev, e->id); 1108 1092 out: 1109 1093 kfree(e); ··· 1689 1671 return ret; 1690 1672 1691 1673 ret = mt7996_register_phy(dev, MT_BAND2); 1674 + if (ret) 1675 + return ret; 1676 + 1677 + ret = mt7996_npu_hw_init(dev); 1692 1678 if (ret) 1693 1679 return ret; 1694 1680
+51 -11
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 718 718 status->flag |= RX_FLAG_8023; 719 719 mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb, 720 720 *info); 721 + mt76_npu_check_ppe(&dev->mt76, skb, *info); 721 722 } 722 723 723 724 if (rxv && !(status->flag & RX_FLAG_8023)) { ··· 795 794 u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 796 795 __le16 fc = hdr->frame_control, sc = hdr->seq_ctrl; 797 796 u16 seqno = le16_to_cpu(sc); 797 + bool hw_bigtk = false; 798 798 u8 fc_type, fc_stype; 799 799 u32 val; 800 800 ··· 821 819 info->flags & IEEE80211_TX_CTL_USE_MINRATE) 822 820 val |= MT_TXD1_FIXED_RATE; 823 821 824 - if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) { 822 + if (is_mt7990(&dev->mt76) && ieee80211_is_beacon(fc) && 823 + (wcid->hw_key_idx2 == 6 || wcid->hw_key_idx2 == 7)) 824 + hw_bigtk = true; 825 + 826 + if ((key && multicast && ieee80211_is_robust_mgmt_frame(skb)) || hw_bigtk) { 825 827 val |= MT_TXD1_BIP; 826 828 txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); 827 829 } ··· 1040 1034 struct ieee80211_sta *sta, 1041 1035 struct mt76_tx_info *tx_info) 1042 1036 { 1037 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; 1043 1038 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 1044 1039 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 1045 1040 struct ieee80211_key_conf *key = info->control.hw_key; 1046 1041 struct ieee80211_vif *vif = info->control.vif; 1042 + struct mt7996_vif *mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; 1043 + struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL; 1044 + struct mt76_vif_link *mlink = NULL; 1047 1045 struct mt76_txwi_cache *t; 1048 1046 int id, i, pid, nbuf = tx_info->nbuf - 1; 1049 1047 bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 1050 1048 __le32 *ptr = (__le32 *)txwi_ptr; 1051 1049 u8 *txwi = (u8 *)txwi_ptr; 1050 + u8 link_id; 1052 1051 1053 1052 if (unlikely(tx_info->skb->len <= ETH_HLEN)) 1054 1053 return -EINVAL; 1055 1054 1056 1055 if (!wcid) 1057 1056 wcid = &dev->mt76.global_wcid; 1057 + 1058 + if ((is_8023 || ieee80211_is_data_qos(hdr->frame_control)) && sta->mlo && 1059 + likely(tx_info->skb->protocol != cpu_to_be16(ETH_P_PAE))) { 1060 + u8 tid = tx_info->skb->priority & IEEE80211_QOS_CTL_TID_MASK; 1061 + 1062 + link_id = (tid % 2) ? msta->seclink_id : msta->deflink_id; 1063 + } else { 1064 + link_id = u32_get_bits(info->control.flags, 1065 + IEEE80211_TX_CTRL_MLO_LINK); 1066 + } 1067 + 1068 + if (link_id != wcid->link_id && link_id != IEEE80211_LINK_UNSPECIFIED) { 1069 + if (msta) { 1070 + struct mt7996_sta_link *msta_link = 1071 + rcu_dereference(msta->link[link_id]); 1072 + 1073 + if (msta_link) 1074 + wcid = &msta_link->wcid; 1075 + } else if (mvif) { 1076 + mlink = rcu_dereference(mvif->mt76.link[link_id]); 1077 + if (mlink && mlink->wcid) 1078 + wcid = mlink->wcid; 1079 + } 1080 + } 1058 1081 1059 1082 t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); 1060 1083 t->skb = tx_info->skb; ··· 1189 1154 if (!is_8023 && mt7996_tx_use_mgmt(dev, tx_info->skb)) 1190 1155 txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); 1191 1156 1192 - if (vif) { 1193 - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 1194 - struct mt76_vif_link *mlink = NULL; 1195 - 1157 + if (mvif) { 1196 1158 if (wcid->offchannel) 1197 1159 mlink = rcu_dereference(mvif->mt76.offchannel_link); 1198 1160 if (!mlink) ··· 1713 1681 if (!list_empty(&dev->wed_rro.page_cache)) { 1714 1682 p = list_first_entry(&dev->wed_rro.page_cache, 1715 1683 struct mt7996_msdu_page, list); 1716 - if (p) 1717 - list_del(&p->list); 1684 + list_del(&p->list); 1718 1685 } 1719 1686 1720 1687 spin_unlock(&dev->wed_rro.lock); ··· 2368 2337 if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 2369 2338 continue; 2370 2339 2371 - ret = mt7996_run(&dev->phy); 2340 + ret = mt7996_run(phy); 2372 2341 if (ret) 2373 2342 goto out; 2374 2343 } ··· 2450 2419 cancel_work_sync(&dev->wed_rro.work); 2451 2420 mt7996_for_each_phy(dev, phy) 2452 2421 cancel_delayed_work_sync(&phy->mt76->mac_work); 2422 + 2423 + mt76_abort_scan(&dev->mt76); 2453 2424 2454 2425 mutex_lock(&dev->mt76.mutex); 2455 2426 for (i = 0; i < 10; i++) { ··· 2569 2536 2570 2537 mutex_lock(&dev->mt76.mutex); 2571 2538 2539 + mt7996_npu_hw_stop(dev); 2540 + 2572 2541 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); 2573 2542 2574 2543 if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { ··· 2586 2551 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); 2587 2552 mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); 2588 2553 2589 - /* enable DMA Tx/Tx and interrupt */ 2554 + /* enable DMA Rx/Tx and interrupt */ 2590 2555 mt7996_dma_start(dev, false, false); 2591 2556 2592 2557 if (!is_mt7996(&dev->mt76) && dev->mt76.hwrro_mode == MT76_HWRRO_V3) ··· 2634 2599 local_bh_enable(); 2635 2600 2636 2601 ieee80211_wake_queues(hw); 2602 + mt7996_update_beacons(dev); 2637 2603 2638 2604 mutex_unlock(&dev->mt76.mutex); 2639 2605 2640 - mt7996_update_beacons(dev); 2606 + mt7996_npu_hw_init(dev); 2641 2607 2642 2608 mt7996_for_each_phy(dev, phy) 2643 2609 ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, ··· 2890 2854 LIST_HEAD(list); 2891 2855 u32 changed; 2892 2856 2857 + mutex_lock(&dev->mt76.mutex); 2858 + 2893 2859 spin_lock_bh(&dev->mt76.sta_poll_lock); 2894 2860 list_splice_init(&dev->sta_rc_list, &list); 2895 2861 ··· 2924 2886 } 2925 2887 2926 2888 spin_unlock_bh(&dev->mt76.sta_poll_lock); 2889 + 2890 + mutex_unlock(&dev->mt76.mutex); 2927 2891 } 2928 2892 2929 2893 void mt7996_mac_work(struct work_struct *work)
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/mac.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */
+99 -54
drivers/net/wireless/mediatek/mt76/mt7996/main.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 90 90 { 91 91 } 92 92 93 - static inline int get_free_idx(u32 mask, u8 start, u8 end) 93 + static inline int get_free_idx(u64 mask, u8 start, u8 end) 94 94 { 95 - return ffs(~mask & GENMASK(end, start)); 95 + if (~mask & GENMASK_ULL(end, start)) 96 + return __ffs64(~mask & GENMASK_ULL(end, start)) + 1; 97 + return 0; 96 98 } 97 99 98 100 static int get_omac_idx(enum nl80211_iftype type, u64 mask) ··· 249 247 else if (idx == *wcid_keyidx) 250 248 *wcid_keyidx = -1; 251 249 252 - if (cmd != SET_KEY && sta) 250 + /* only do remove key for BIGTK */ 251 + if (cmd != SET_KEY && !is_bigtk) 253 252 return 0; 254 253 255 254 mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key); 256 255 257 - err = mt7996_mcu_add_key(&dev->mt76, vif, key, 256 + err = mt7996_mcu_add_key(&dev->mt76, link, key, 258 257 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), 259 258 &msta_link->wcid, cmd); 260 259 ··· 311 308 if (idx < 0) 312 309 return -ENOSPC; 313 310 314 - if (!dev->mld_idx_mask) { /* first link in the group */ 315 - mvif->mld_group_idx = get_own_mld_idx(dev->mld_idx_mask, true); 316 - mvif->mld_remap_idx = get_free_idx(dev->mld_remap_idx_mask, 317 - 0, 15); 318 - } 319 - 320 311 mld_idx = get_own_mld_idx(dev->mld_idx_mask, false); 321 312 if (mld_idx < 0) 322 313 return -ENOSPC; ··· 328 331 return ret; 329 332 330 333 dev->mt76.vif_mask |= BIT_ULL(mlink->idx); 331 - if (!dev->mld_idx_mask) { 332 - dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx); 333 - dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx); 334 - } 335 334 dev->mld_idx_mask |= BIT_ULL(link->mld_idx); 336 335 phy->omac_mask |= BIT_ULL(mlink->omac_idx); 337 336 ··· 336 343 INIT_LIST_HEAD(&msta_link->rc_list); 337 344 msta_link->wcid.idx = idx; 338 345 msta_link->wcid.link_id = link_conf->link_id; 346 + msta_link->wcid.link_valid = ieee80211_vif_is_mld(vif); 339 347 msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET; 340 348 mt76_wcid_init(&msta_link->wcid, band_idx); 341 349 ··· 370 376 371 377 ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it); 372 378 373 - if (mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED) 379 + if (!mlink->wcid->offchannel && 380 + mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED) 374 381 mvif->mt76.deflink_id = link_conf->link_id; 375 382 376 383 return 0; ··· 392 397 }; 393 398 int idx = msta_link->wcid.idx; 394 399 395 - ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it); 400 + if (!mlink->wcid->offchannel) 401 + ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it); 396 402 397 403 mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL, 398 404 CONN_STATE_DISCONNECT, false); ··· 403 407 404 408 rcu_assign_pointer(dev->mt76.wcid[idx], NULL); 405 409 406 - if (mvif->mt76.deflink_id == link_conf->link_id) { 410 + if (!mlink->wcid->offchannel && 411 + mvif->mt76.deflink_id == link_conf->link_id) { 407 412 struct ieee80211_bss_conf *iter; 408 413 unsigned int link_id; 409 414 ··· 420 423 dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx); 421 424 dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx); 422 425 phy->omac_mask &= ~BIT_ULL(mlink->omac_idx); 423 - if (!(dev->mld_idx_mask & ~BIT_ULL(mvif->mld_group_idx))) { 424 - /* last link */ 425 - dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx); 426 - dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx); 427 - } 428 426 429 427 spin_lock_bh(&dev->mt76.sta_poll_lock); 430 428 if (!list_empty(&msta_link->wcid.poll_list)) ··· 657 665 unsigned int link_id, u16 queue, 658 666 const struct ieee80211_tx_queue_params *params) 659 667 { 660 - struct mt7996_dev *dev = mt7996_hw_dev(hw); 661 - struct mt7996_vif_link *mlink = mt7996_vif_link(dev, vif, link_id); 668 + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 669 + struct mt7996_vif_link_info *link_info = &mvif->link_info[link_id]; 662 670 static const u8 mq_to_aci[] = { 663 671 [IEEE80211_AC_VO] = 3, 664 672 [IEEE80211_AC_VI] = 2, ··· 667 675 }; 668 676 669 677 /* firmware uses access class index */ 670 - mlink->queue_params[mq_to_aci[queue]] = *params; 678 + link_info->queue_params[mq_to_aci[queue]] = *params; 671 679 /* no need to update right away, we'll get BSS_CHANGED_QOS */ 672 680 673 681 return 0; ··· 954 962 955 963 msta_link = &msta->deflink; 956 964 msta->deflink_id = link_id; 965 + msta->seclink_id = msta->deflink_id; 957 966 958 967 for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { 959 968 struct mt76_txq *mtxq; ··· 969 976 msta_link = kzalloc(sizeof(*msta_link), GFP_KERNEL); 970 977 if (!msta_link) 971 978 return -ENOMEM; 979 + 980 + if (msta->seclink_id == msta->deflink_id && 981 + (sta->valid_links & ~BIT(msta->deflink_id))) 982 + msta->seclink_id = __ffs(sta->valid_links & 983 + ~BIT(msta->deflink_id)); 972 984 } 973 985 974 986 INIT_LIST_HEAD(&msta_link->rc_list); ··· 982 984 msta_link->wcid.sta = 1; 983 985 msta_link->wcid.idx = idx; 984 986 msta_link->wcid.link_id = link_id; 987 + msta_link->wcid.link_valid = !!sta->valid_links; 985 988 msta_link->wcid.def_wcid = &msta->deflink.wcid; 986 989 987 990 ewma_avg_signal_init(&msta_link->avg_ack_signal); ··· 1048 1049 if (msta->deflink_id == link_id) { 1049 1050 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; 1050 1051 continue; 1052 + } else if (msta->seclink_id == link_id) { 1053 + msta->seclink_id = IEEE80211_LINK_UNSPECIFIED; 1051 1054 } 1052 1055 1053 1056 kfree_rcu(msta_link, rcu_head); ··· 1145 1144 mutex_lock(&dev->mt76.mutex); 1146 1145 1147 1146 msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; 1147 + msta->seclink_id = IEEE80211_LINK_UNSPECIFIED; 1148 1148 msta->vif = mvif; 1149 1149 err = mt7996_mac_sta_add_links(dev, vif, sta, links); 1150 1150 ··· 1162 1160 unsigned long links = sta->valid_links; 1163 1161 struct ieee80211_link_sta *link_sta; 1164 1162 unsigned int link_id; 1163 + int err = 0; 1164 + 1165 + mutex_lock(&dev->mt76.mutex); 1165 1166 1166 1167 for_each_sta_active_link(vif, sta, link_sta, link_id) { 1167 1168 struct ieee80211_bss_conf *link_conf; 1168 1169 struct mt7996_sta_link *msta_link; 1169 1170 struct mt7996_vif_link *link; 1170 - int i, err; 1171 + int i; 1171 1172 1172 1173 link_conf = link_conf_dereference_protected(vif, link_id); 1173 1174 if (!link_conf) ··· 1190 1185 link, msta_link, 1191 1186 CONN_STATE_CONNECT, true); 1192 1187 if (err) 1193 - return err; 1188 + goto unlock; 1194 1189 1195 1190 err = mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif, 1196 1191 link_id, false); 1197 1192 if (err) 1198 - return err; 1193 + goto unlock; 1199 1194 1200 1195 msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET; 1201 1196 break; ··· 1204 1199 link, msta_link, 1205 1200 CONN_STATE_PORT_SECURE, false); 1206 1201 if (err) 1207 - return err; 1202 + goto unlock; 1208 1203 break; 1209 1204 case MT76_STA_EVENT_DISASSOC: 1210 1205 for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++) 1211 1206 mt7996_mac_twt_teardown_flow(dev, link, 1212 1207 msta_link, i); 1213 1208 1214 - if (sta->mlo && links == BIT(link_id)) /* last link */ 1215 - mt7996_mcu_teardown_mld_sta(dev, link, 1216 - msta_link); 1217 - else 1209 + if (!sta->mlo) 1218 1210 mt7996_mcu_add_sta(dev, link_conf, link_sta, 1219 1211 link, msta_link, 1220 1212 CONN_STATE_DISCONNECT, false); 1213 + else if (sta->mlo && links == BIT(link_id)) /* last link */ 1214 + mt7996_mcu_teardown_mld_sta(dev, link, 1215 + msta_link); 1221 1216 msta_link->wcid.sta_disabled = 1; 1222 1217 msta_link->wcid.sta = 0; 1223 1218 links = links & ~BIT(link_id); 1224 1219 break; 1225 1220 } 1226 1221 } 1222 + unlock: 1223 + mutex_unlock(&dev->mt76.mutex); 1227 1224 1228 - return 0; 1225 + return err; 1229 1226 } 1230 1227 1231 1228 static void ··· 1346 1339 } 1347 1340 1348 1341 if (mvif) { 1349 - struct mt76_vif_link *mlink = &mvif->deflink.mt76; 1342 + struct mt76_vif_link *mlink; 1350 1343 1351 - if (link_id < IEEE80211_LINK_UNSPECIFIED) 1352 - mlink = rcu_dereference(mvif->mt76.link[link_id]); 1353 - 1354 - if (mlink->wcid) 1344 + mlink = rcu_dereference(mvif->mt76.link[link_id]); 1345 + if (mlink && mlink->wcid) 1355 1346 wcid = mlink->wcid; 1356 1347 1357 1348 if (mvif->mt76.roc_phy && ··· 1357 1352 mphy = mvif->mt76.roc_phy; 1358 1353 if (mphy->roc_link) 1359 1354 wcid = mphy->roc_link->wcid; 1360 - } else { 1355 + } else if (mlink) { 1361 1356 mphy = mt76_vif_link_phy(mlink); 1362 1357 } 1363 1358 } ··· 1367 1362 goto unlock; 1368 1363 } 1369 1364 1370 - if (msta && link_id < IEEE80211_LINK_UNSPECIFIED) { 1365 + if (msta) { 1371 1366 struct mt7996_sta_link *msta_link; 1372 1367 1373 1368 msta_link = rcu_dereference(msta->link[link_id]); ··· 2164 2159 return ret; 2165 2160 } 2166 2161 2167 - #ifdef CONFIG_NET_MEDIATEK_SOC_WED 2168 2162 static int 2169 2163 mt7996_net_fill_forward_path(struct ieee80211_hw *hw, 2170 2164 struct ieee80211_vif *vif, ··· 2171 2167 struct net_device_path_ctx *ctx, 2172 2168 struct net_device_path *path) 2173 2169 { 2174 - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 2175 2170 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 2176 2171 struct mt7996_dev *dev = mt7996_hw_dev(hw); 2177 2172 struct mtk_wed_device *wed = &dev->mt76.mmio.wed; 2178 2173 struct mt7996_sta_link *msta_link; 2179 - struct mt76_vif_link *mlink; 2174 + struct mt7996_vif_link *link; 2180 2175 2181 - mlink = rcu_dereference(mvif->mt76.link[msta->deflink_id]); 2182 - if (!mlink) 2176 + link = mt7996_vif_link(dev, vif, msta->deflink_id); 2177 + if (!link) 2183 2178 return -EIO; 2184 2179 2185 2180 msta_link = rcu_dereference(msta->link[msta->deflink_id]); ··· 2193 2190 (is_mt7992(&dev->mt76) && msta_link->wcid.phy_idx == MT_BAND1))) 2194 2191 wed = &dev->mt76.mmio.wed_hif2; 2195 2192 2196 - if (!mtk_wed_device_active(wed)) 2193 + if (!mtk_wed_device_active(wed) && 2194 + !mt76_npu_device_active(&dev->mt76)) 2197 2195 return -ENODEV; 2198 2196 2199 2197 path->type = DEV_PATH_MTK_WDMA; 2200 2198 path->dev = ctx->dev; 2201 - path->mtk_wdma.wdma_idx = wed->wdma_idx; 2202 - path->mtk_wdma.bss = mlink->idx; 2199 + #ifdef CONFIG_NET_MEDIATEK_SOC_WED 2200 + if (mtk_wed_device_active(wed)) 2201 + path->mtk_wdma.wdma_idx = wed->wdma_idx; 2202 + else 2203 + #endif 2204 + path->mtk_wdma.wdma_idx = link->mt76.band_idx; 2205 + path->mtk_wdma.bss = link->mt76.idx; 2203 2206 path->mtk_wdma.queue = 0; 2204 2207 path->mtk_wdma.wcid = msta_link->wcid.idx; 2205 2208 ··· 2219 2210 return 0; 2220 2211 } 2221 2212 2222 - #endif 2223 - 2224 2213 static int 2225 2214 mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2226 2215 u16 old_links, u16 new_links, 2227 2216 struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) 2228 2217 { 2229 - return 0; 2218 + struct mt7996_dev *dev = mt7996_hw_dev(hw); 2219 + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 2220 + int ret = 0; 2221 + 2222 + mutex_lock(&dev->mt76.mutex); 2223 + 2224 + if (!old_links) { 2225 + int idx; 2226 + 2227 + idx = get_own_mld_idx(dev->mld_idx_mask, true); 2228 + if (idx < 0) { 2229 + ret = -ENOSPC; 2230 + goto out; 2231 + } 2232 + mvif->mld_group_idx = idx; 2233 + dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx); 2234 + 2235 + idx = get_free_idx(dev->mld_remap_idx_mask, 0, 15) - 1; 2236 + if (idx < 0) { 2237 + ret = -ENOSPC; 2238 + goto out; 2239 + } 2240 + mvif->mld_remap_idx = idx; 2241 + dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx); 2242 + } 2243 + 2244 + if (new_links) 2245 + goto out; 2246 + 2247 + dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx); 2248 + dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx); 2249 + 2250 + out: 2251 + mutex_unlock(&dev->mt76.mutex); 2252 + 2253 + return ret; 2230 2254 } 2231 2255 2232 2256 static void ··· 2325 2283 .twt_teardown_request = mt7996_twt_teardown_request, 2326 2284 #ifdef CONFIG_MAC80211_DEBUGFS 2327 2285 .sta_add_debugfs = mt7996_sta_add_debugfs, 2286 + .link_sta_add_debugfs = mt7996_link_sta_add_debugfs, 2328 2287 #endif 2329 2288 .set_radar_background = mt7996_set_radar_background, 2330 - #ifdef CONFIG_NET_MEDIATEK_SOC_WED 2331 2289 .net_fill_forward_path = mt7996_net_fill_forward_path, 2290 + #ifdef CONFIG_NET_MEDIATEK_SOC_WED 2332 2291 .net_setup_tc = mt76_wed_net_setup_tc, 2292 + #elif defined(CONFIG_MT7996_NPU) 2293 + .net_setup_tc = mt76_npu_net_setup_tc, 2333 2294 #endif 2334 2295 .change_vif_links = mt7996_change_vif_links, 2335 2296 .change_sta_links = mt7996_mac_sta_change_links,
+49 -29
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 317 317 uni_txd->option = MCU_CMD_UNI_QUERY_ACK; 318 318 else 319 319 uni_txd->option = MCU_CMD_UNI_EXT_ACK; 320 + 321 + if (mcu_cmd == MCU_UNI_CMD_SDO) 322 + uni_txd->option &= ~MCU_CMD_ACK; 320 323 321 324 if ((cmd & __MCU_CMD_FIELD_WA) && (cmd & __MCU_CMD_FIELD_WM)) 322 325 uni_txd->s2d_index = MCU_S2D_H2CN; ··· 1037 1034 struct mt76_connac_bss_basic_tlv *bss; 1038 1035 u32 type = CONNECTION_INFRA_AP; 1039 1036 u16 sta_wlan_idx = wlan_idx; 1040 - struct ieee80211_sta *sta; 1041 1037 struct tlv *tlv; 1042 1038 int idx; 1043 1039 ··· 1047 1045 break; 1048 1046 case NL80211_IFTYPE_STATION: 1049 1047 if (enable) { 1050 - rcu_read_lock(); 1051 - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); 1052 - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ 1053 - if (sta) { 1054 - struct mt76_wcid *wcid; 1048 + struct ieee80211_sta *sta; 1055 1049 1056 - wcid = (struct mt76_wcid *)sta->drv_priv; 1057 - sta_wlan_idx = wcid->idx; 1050 + rcu_read_lock(); 1051 + sta = ieee80211_find_sta(vif, link_conf->bssid); 1052 + if (sta) { 1053 + struct mt7996_sta *msta = (void *)sta->drv_priv; 1054 + struct mt7996_sta_link *msta_link; 1055 + int link_id = link_conf->link_id; 1056 + 1057 + msta_link = rcu_dereference(msta->link[link_id]); 1058 + if (msta_link) 1059 + sta_wlan_idx = msta_link->wcid.idx; 1058 1060 } 1059 1061 rcu_read_unlock(); 1060 1062 } ··· 1075 1069 tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*bss)); 1076 1070 1077 1071 bss = (struct mt76_connac_bss_basic_tlv *)tlv; 1078 - bss->bcn_interval = cpu_to_le16(link_conf->beacon_int); 1079 - bss->dtim_period = link_conf->dtim_period; 1080 1072 bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); 1081 1073 bss->sta_idx = cpu_to_le16(sta_wlan_idx); 1082 1074 bss->conn_type = cpu_to_le32(type); ··· 1094 1090 1095 1091 memcpy(bss->bssid, link_conf->bssid, ETH_ALEN); 1096 1092 bss->bcn_interval = cpu_to_le16(link_conf->beacon_int); 1097 - bss->dtim_period = vif->bss_conf.dtim_period; 1093 + bss->dtim_period = link_conf->dtim_period; 1098 1094 bss->phymode = mt76_connac_get_phy_mode(phy, vif, 1099 1095 chandef->chan->band, NULL); 1100 - bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, &vif->bss_conf, 1096 + bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, link_conf, 1101 1097 chandef->chan->band); 1102 1098 1103 1099 return 0; ··· 1826 1822 bf->ibf_nrow = tx_ant; 1827 1823 1828 1824 if (link_sta->eht_cap.has_eht || link_sta->he_cap.has_he) 1829 - bf->ibf_timeout = is_mt7996(&dev->mt76) ? MT7996_IBF_TIMEOUT : 1830 - MT7992_IBF_TIMEOUT; 1825 + bf->ibf_timeout = is_mt7992(&dev->mt76) ? MT7992_IBF_TIMEOUT : 1826 + MT7996_IBF_TIMEOUT; 1831 1827 else if (!ebf && link_sta->bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) 1832 1828 bf->ibf_timeout = MT7996_IBF_TIMEOUT_LEGACY; 1833 1829 else ··· 2394 2390 mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx); 2395 2391 2396 2392 if (nlinks > 1) { 2397 - link_id = __ffs(sta->valid_links & ~BIT(msta->deflink_id)); 2398 - msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); 2393 + msta_link = mt76_dereference(msta->link[msta->seclink_id], 2394 + &dev->mt76); 2399 2395 if (!msta_link) 2400 2396 return; 2401 2397 } ··· 2530 2526 } 2531 2527 2532 2528 static int 2533 - mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid, 2529 + mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid, 2534 2530 struct sk_buff *skb, 2535 2531 struct ieee80211_key_conf *key, 2536 2532 enum set_key_cmd cmd) ··· 2542 2538 2543 2539 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); 2544 2540 sec = (struct sta_rec_sec_uni *)tlv; 2545 - sec->add = 0; 2541 + /* due to connac3 FW design, we only do remove key for BIGTK; even for 2542 + * removal, the field should be filled with SET_KEY 2543 + */ 2544 + sec->add = SET_KEY; 2546 2545 sec->n_cipher = 1; 2547 2546 sec_key = &sec->key[0]; 2548 2547 sec_key->wlan_idx = cpu_to_le16(wcid->idx); ··· 2585 2578 case WLAN_CIPHER_SUITE_BIP_GMAC_256: 2586 2579 sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256; 2587 2580 break; 2581 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 2582 + if (!is_mt7990(dev)) 2583 + return -EOPNOTSUPP; 2584 + sec_key->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_256; 2585 + break; 2588 2586 default: 2589 2587 return -EOPNOTSUPP; 2590 2588 } 2591 2589 2592 - sec_key->bcn_mode = BP_SW_MODE; 2590 + sec_key->bcn_mode = is_mt7990(dev) ? BP_HW_MODE : BP_SW_MODE; 2593 2591 2594 2592 return 0; 2595 2593 } 2596 2594 2597 - int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, 2595 + int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link, 2598 2596 struct ieee80211_key_conf *key, int mcu_cmd, 2599 2597 struct mt76_wcid *wcid, enum set_key_cmd cmd) 2600 2598 { 2601 - struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; 2602 2599 struct sk_buff *skb; 2603 2600 int ret; 2604 2601 2605 - skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, 2606 - MT7996_STA_UPDATE_MAX_SIZE); 2602 + skb = __mt76_connac_mcu_alloc_sta_req(dev, (struct mt76_vif_link *)link, 2603 + wcid, MT7996_STA_UPDATE_MAX_SIZE); 2607 2604 if (IS_ERR(skb)) 2608 2605 return PTR_ERR(skb); 2609 2606 2610 - ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd); 2607 + ret = mt7996_mcu_sta_key_tlv(dev, wcid, skb, key, cmd); 2611 2608 if (ret) { 2612 2609 dev_kfree_skb(skb); 2613 2610 return ret; ··· 2731 2720 static void 2732 2721 mt7996_mcu_beacon_cont(struct mt7996_dev *dev, 2733 2722 struct ieee80211_bss_conf *link_conf, 2723 + struct mt7996_vif_link *link, 2734 2724 struct sk_buff *rskb, struct sk_buff *skb, 2735 2725 struct bss_bcn_content_tlv *bcn, 2736 2726 struct ieee80211_mutable_offsets *offs) 2737 2727 { 2738 - struct mt76_wcid *wcid = &dev->mt76.global_wcid; 2739 - u8 *buf; 2728 + u8 *buf, keyidx = link->msta_link.wcid.hw_key_idx2; 2729 + struct mt76_wcid *wcid; 2730 + 2731 + if (is_mt7990(&dev->mt76) && (keyidx == 6 || keyidx == 7)) 2732 + wcid = &link->msta_link.wcid; 2733 + else 2734 + wcid = &dev->mt76.global_wcid; 2740 2735 2741 2736 bcn->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); 2742 2737 bcn->tim_ie_pos = cpu_to_le16(offs->tim_offset); ··· 2817 2800 info = IEEE80211_SKB_CB(skb); 2818 2801 info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mlink->band_idx); 2819 2802 2820 - mt7996_mcu_beacon_cont(dev, link_conf, rskb, skb, bcn, &offs); 2803 + mt7996_mcu_beacon_cont(dev, link_conf, link, rskb, skb, bcn, &offs); 2821 2804 if (link_conf->bssid_indicator) 2822 2805 mt7996_mcu_beacon_mbss(rskb, skb, bcn, &offs); 2823 2806 mt7996_mcu_beacon_cntdwn(rskb, skb, &offs, link_conf->csa_active); ··· 3431 3414 #define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \ 3432 3415 WMM_CW_MAX_SET | WMM_TXOP_SET) 3433 3416 struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf); 3417 + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 3418 + unsigned int link_id = link_conf->link_id; 3419 + struct mt7996_vif_link_info *link_info = &mvif->link_info[link_id]; 3434 3420 struct { 3435 3421 u8 bss_idx; 3436 3422 u8 __rsv[3]; ··· 3451 3431 skb_put_data(skb, &hdr, sizeof(hdr)); 3452 3432 3453 3433 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 3454 - struct ieee80211_tx_queue_params *q = &link->queue_params[ac]; 3434 + struct ieee80211_tx_queue_params *q = &link_info->queue_params[ac]; 3455 3435 struct edca *e; 3456 3436 struct tlv *tlv; 3457 3437
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */
+13 -3
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 595 595 596 596 wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE; 597 597 wed->wlan.token_start = MT7996_TOKEN_SIZE - wed->wlan.nbuf; 598 + wed->wlan.hif2 = hif2; 598 599 599 600 wed->wlan.amsdu_max_subframes = 8; 600 601 wed->wlan.amsdu_max_len = 1536; ··· 707 706 static void mt7996_rx_poll_complete(struct mt76_dev *mdev, 708 707 enum mt76_rxq_id q) 709 708 { 710 - struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 709 + if (q == MT_RXQ_NPU0 || q == MT_RXQ_NPU1) { 710 + struct airoha_npu *npu; 711 711 712 - mt7996_irq_enable(dev, MT_INT_RX(q)); 712 + npu = rcu_dereference(mdev->mmio.npu); 713 + if (npu) 714 + airoha_npu_wlan_enable_irq(npu, q - MT_RXQ_NPU0); 715 + } else { 716 + struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, 717 + mt76); 718 + 719 + mt7996_irq_enable(dev, MT_INT_RX(q)); 720 + } 713 721 } 714 722 715 723 /* TODO: support 2/4/6/8 MSI-X vectors */
+34 -4
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 243 243 struct mt7996_sta_link deflink; /* must be first */ 244 244 struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; 245 245 u8 deflink_id; 246 + u8 seclink_id; 246 247 247 248 struct mt7996_vif *vif; 248 249 }; ··· 254 253 struct mt7996_sta_link msta_link; 255 254 struct mt7996_phy *phy; 256 255 257 - struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; 258 256 struct cfg80211_bitrate_mask bitrate_mask; 259 257 260 258 u8 mld_idx; 261 259 }; 262 260 261 + struct mt7996_vif_link_info { 262 + struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; 263 + }; 264 + 263 265 struct mt7996_vif { 264 266 struct mt7996_vif_link deflink; /* must be first */ 265 267 struct mt76_vif_data mt76; 268 + 269 + struct mt7996_vif_link_info link_info[IEEE80211_MLD_MAX_NUM_LINKS]; 266 270 267 271 u8 mld_group_idx; 268 272 u8 mld_remap_idx; ··· 787 781 788 782 static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy) 789 783 { 790 - int max_nss = hweight8(phy->mt76->hw->wiphy->available_antennas_tx); 784 + int max_nss = hweight16(phy->orig_antenna_mask); 791 785 int cur_nss = hweight8(phy->mt76->antenna_mask); 792 786 u16 tx_chainmask = phy->mt76->chainmask; 793 787 ··· 849 843 int mt7996_init_debugfs(struct mt7996_dev *dev); 850 844 void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len); 851 845 bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len); 852 - int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, 846 + int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link, 853 847 struct ieee80211_key_conf *key, int mcu_cmd, 854 848 struct mt76_wcid *wcid, enum set_key_cmd cmd); 855 849 int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, ··· 864 858 #ifdef CONFIG_MAC80211_DEBUGFS 865 859 void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 866 860 struct ieee80211_sta *sta, struct dentry *dir); 861 + void mt7996_link_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 862 + struct ieee80211_link_sta *link_sta, 863 + struct dentry *dir); 867 864 #endif 868 865 int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, 869 866 bool hif2, int *irq); ··· 877 868 #endif 878 869 879 870 int mt7996_dma_rro_init(struct mt7996_dev *dev); 871 + 872 + #ifdef CONFIG_MT7996_NPU 873 + int mt7996_npu_hw_init(struct mt7996_dev *dev); 874 + int mt7996_npu_hw_stop(struct mt7996_dev *dev); 875 + int mt7996_npu_rx_queues_init(struct mt7996_dev *dev); 876 + #else 877 + static inline int mt7996_npu_hw_init(struct mt7996_dev *dev) 878 + { 879 + return 0; 880 + } 881 + 882 + static inline int mt7996_npu_hw_stop(struct mt7996_dev *dev) 883 + { 884 + return 0; 885 + } 886 + 887 + static inline int mt7996_npu_rx_queues_init(struct mt7996_dev *dev) 888 + { 889 + return 0; 890 + } 891 + #endif /* CONFIG_MT7996_NPU */ 880 892 881 893 #endif
+352
drivers/net/wireless/mediatek/mt76/mt7996/npu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2025 AIROHA Inc 4 + * Author: Lorenzo Bianconi <lorenzo@kernel.org> 5 + */ 6 + #include <linux/kernel.h> 7 + #include <linux/soc/airoha/airoha_offload.h> 8 + 9 + #include "mt7996.h" 10 + 11 + static int mt7996_npu_offload_init(struct mt7996_dev *dev, 12 + struct airoha_npu *npu) 13 + { 14 + phys_addr_t phy_addr = dev->mt76.mmio.phy_addr; 15 + u32 val, hif1_ofs = 0, dma_addr; 16 + int i, err; 17 + 18 + err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION, 19 + &val, GFP_KERNEL); 20 + if (err) { 21 + dev_warn(dev->mt76.dev, "failed getting NPU fw version\n"); 22 + return err; 23 + } 24 + 25 + dev_info(dev->mt76.dev, "NPU version: %0d.%d\n", 26 + (val >> 16) & 0xffff, val & 0xffff); 27 + 28 + err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE, 29 + dev->mt76.mmio.npu_type, GFP_KERNEL); 30 + if (err) { 31 + dev_warn(dev->mt76.dev, 32 + "failed setting NPU wlan PCIe port type\n"); 33 + return err; 34 + } 35 + 36 + if (dev->hif2) 37 + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); 38 + 39 + for (i = MT_BAND0; i < MT_BAND2; i++) { 40 + dma_addr = phy_addr; 41 + if (i) 42 + dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90 + 43 + hif1_ofs; 44 + else 45 + dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80; 46 + 47 + err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_PCIE_ADDR, 48 + dma_addr, GFP_KERNEL); 49 + if (err) { 50 + dev_warn(dev->mt76.dev, 51 + "failed setting NPU wlan PCIe desc addr\n"); 52 + return err; 53 + } 54 + 55 + err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC, 56 + MT7996_RX_RING_SIZE, GFP_KERNEL); 57 + if (err) { 58 + dev_warn(dev->mt76.dev, 59 + "failed setting NPU wlan PCIe desc size\n"); 60 + return err; 61 + } 62 + 63 + dma_addr = phy_addr; 64 + if (i) 65 + dma_addr += MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs; 66 + else 67 + dma_addr += MT_TXQ_RING_BASE(0) + 0x120; 68 + 69 + err = mt76_npu_send_msg(npu, i, 70 + WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR, 71 + dma_addr, GFP_KERNEL); 72 + if (err) { 73 + dev_warn(dev->mt76.dev, 74 + "failed setting NPU wlan tx desc addr\n"); 75 + return err; 76 + } 77 + } 78 + 79 + err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_PCIE_ADDR, 80 + phy_addr + MT_RXQ_RRO_AP_RING_BASE, 81 + GFP_KERNEL); 82 + if (err) { 83 + dev_warn(dev->mt76.dev, 84 + "failed setting NPU wlan rxdmad_c addr\n"); 85 + return err; 86 + } 87 + 88 + err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_DESC, 89 + MT7996_RX_RING_SIZE, GFP_KERNEL); 90 + if (err) { 91 + dev_warn(dev->mt76.dev, 92 + "failed setting NPU wlan rxdmad_c desc size\n"); 93 + return err; 94 + } 95 + 96 + err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR, 97 + phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL); 98 + if (err) { 99 + dev_warn(dev->mt76.dev, 100 + "failed setting NPU wlan rro_ack_sn desc addr\n"); 101 + return err; 102 + } 103 + 104 + err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE, 105 + MT7996_HW_TOKEN_SIZE, GFP_KERNEL); 106 + if (err) 107 + return err; 108 + 109 + dev->mt76.token_start = MT7996_HW_TOKEN_SIZE; 110 + 111 + return 0; 112 + } 113 + 114 + static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu) 115 + { 116 + u32 val; 117 + int err; 118 + 119 + err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE, 120 + &val, GFP_KERNEL); 121 + if (err) { 122 + dev_warn(dev->mt76.dev, 123 + "failed retriving NPU wlan rx ring0 addr\n"); 124 + return err; 125 + } 126 + writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base); 127 + 128 + err = mt76_npu_get_msg(npu, 1, WLAN_FUNC_GET_WAIT_RXDESC_BASE, 129 + &val, GFP_KERNEL); 130 + if (err) { 131 + dev_warn(dev->mt76.dev, 132 + "failed retriving NPU wlan rx ring1 addr\n"); 133 + return err; 134 + } 135 + writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base); 136 + 137 + err = mt76_npu_get_msg(npu, 9, WLAN_FUNC_GET_WAIT_RXDESC_BASE, 138 + &val, GFP_KERNEL); 139 + if (err) { 140 + dev_warn(dev->mt76.dev, 141 + "failed retriving NPU wlan rxdmad_c ring addr\n"); 142 + return err; 143 + } 144 + writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base); 145 + 146 + return 0; 147 + } 148 + 149 + static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu) 150 + { 151 + int i, err; 152 + 153 + for (i = MT_BAND0; i < MT_BAND2; i++) { 154 + dma_addr_t dma_addr; 155 + u32 val; 156 + 157 + err = mt76_npu_get_msg(npu, i + 5, 158 + WLAN_FUNC_GET_WAIT_RXDESC_BASE, 159 + &val, GFP_KERNEL); 160 + if (err) { 161 + dev_warn(dev->mt76.dev, 162 + "failed retriving NPU wlan tx ring addr\n"); 163 + return err; 164 + } 165 + writel(val, &dev->mt76.phys[i]->q_tx[0]->regs->desc_base); 166 + 167 + if (!dmam_alloc_coherent(dev->mt76.dma_dev, 168 + 256 * MT7996_TX_RING_SIZE, 169 + &dma_addr, GFP_KERNEL)) 170 + return -ENOMEM; 171 + 172 + err = mt76_npu_send_msg(npu, i, 173 + WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE, 174 + dma_addr, GFP_KERNEL); 175 + if (err) { 176 + dev_warn(dev->mt76.dev, 177 + "failed setting NPU wlan queue buf addr\n"); 178 + return err; 179 + } 180 + 181 + if (!dmam_alloc_coherent(dev->mt76.dma_dev, 182 + 256 * MT7996_TX_RING_SIZE, 183 + &dma_addr, GFP_KERNEL)) 184 + return -ENOMEM; 185 + 186 + err = mt76_npu_send_msg(npu, i + 5, 187 + WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE, 188 + dma_addr, GFP_KERNEL); 189 + if (err) { 190 + dev_warn(dev->mt76.dev, 191 + "failed setting NPU wlan tx buf addr\n"); 192 + return err; 193 + } 194 + 195 + if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024, 196 + &dma_addr, GFP_KERNEL)) 197 + return -ENOMEM; 198 + 199 + err = mt76_npu_send_msg(npu, i + 10, 200 + WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE, 201 + dma_addr, GFP_KERNEL); 202 + if (err) { 203 + dev_warn(dev->mt76.dev, 204 + "failed setting NPU wlan tx buf base\n"); 205 + return err; 206 + } 207 + } 208 + 209 + return 0; 210 + } 211 + 212 + static int mt7996_npu_rx_event_init(struct mt7996_dev *dev, 213 + struct airoha_npu *npu) 214 + { 215 + struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MAIN_WA]; 216 + phys_addr_t phy_addr = dev->mt76.mmio.phy_addr; 217 + int err; 218 + 219 + err = mt76_npu_send_msg(npu, 0, 220 + WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE, 221 + q->desc_dma, GFP_KERNEL); 222 + if (err) { 223 + dev_warn(dev->mt76.dev, 224 + "failed setting NPU wlan tx-done ring\n"); 225 + return err; 226 + } 227 + 228 + err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_DESC, 229 + MT7996_RX_MCU_RING_SIZE, GFP_KERNEL); 230 + if (err) { 231 + dev_warn(dev->mt76.dev, 232 + "failed setting NPU wlan descriptors\n"); 233 + return err; 234 + } 235 + 236 + phy_addr += MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA) + 0x20; 237 + err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR, 238 + phy_addr, GFP_KERNEL); 239 + if (err) 240 + dev_warn(dev->mt76.dev, 241 + "failed setting NPU wlan rx pcie address\n"); 242 + return err; 243 + } 244 + 245 + static int mt7996_npu_tx_done_init(struct mt7996_dev *dev, 246 + struct airoha_npu *npu) 247 + { 248 + int err; 249 + 250 + err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, 251 + 0, GFP_KERNEL); 252 + if (err) { 253 + dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr2\n"); 254 + return err; 255 + } 256 + 257 + err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, 258 + 0, GFP_KERNEL); 259 + if (err) 260 + dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr7\n"); 261 + 262 + return err; 263 + } 264 + 265 + int mt7996_npu_rx_queues_init(struct mt7996_dev *dev) 266 + { 267 + int err; 268 + 269 + if (!mt76_npu_device_active(&dev->mt76)) 270 + return 0; 271 + 272 + err = mt76_npu_rx_queue_init(&dev->mt76, 273 + &dev->mt76.q_rx[MT_RXQ_NPU0]); 274 + if (err) 275 + return err; 276 + 277 + return mt76_npu_rx_queue_init(&dev->mt76, 278 + &dev->mt76.q_rx[MT_RXQ_NPU1]); 279 + } 280 + 281 + int mt7996_npu_hw_init(struct mt7996_dev *dev) 282 + { 283 + struct airoha_npu *npu; 284 + int i, err = 0; 285 + 286 + mutex_lock(&dev->mt76.mutex); 287 + 288 + npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex); 289 + if (!npu) 290 + goto unlock; 291 + 292 + err = mt7996_npu_offload_init(dev, npu); 293 + if (err) 294 + goto unlock; 295 + 296 + err = mt7996_npu_rxd_init(dev, npu); 297 + if (err) 298 + goto unlock; 299 + 300 + err = mt7996_npu_txd_init(dev, npu); 301 + if (err) 302 + goto unlock; 303 + 304 + err = mt7996_npu_rx_event_init(dev, npu); 305 + if (err) 306 + goto unlock; 307 + 308 + err = mt7996_npu_tx_done_init(dev, npu); 309 + if (err) 310 + goto unlock; 311 + 312 + for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++) 313 + airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0); 314 + unlock: 315 + mutex_unlock(&dev->mt76.mutex); 316 + 317 + return err; 318 + } 319 + 320 + int mt7996_npu_hw_stop(struct mt7996_dev *dev) 321 + { 322 + struct airoha_npu *npu; 323 + int i, err; 324 + u32 info; 325 + 326 + npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex); 327 + if (!npu) 328 + return 0; 329 + 330 + err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, 331 + 0, GFP_KERNEL); 332 + if (err) 333 + return err; 334 + 335 + for (i = 0; i < 10; i++) { 336 + err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO, 337 + &info, GFP_KERNEL); 338 + if (err) 339 + continue; 340 + 341 + if (info) { 342 + err = -ETIMEDOUT; 343 + continue; 344 + } 345 + } 346 + 347 + if (!err) 348 + err = mt76_npu_send_msg(npu, 6, 349 + WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, 350 + 0, GFP_KERNEL); 351 + return err; 352 + }
+5 -2
drivers/net/wireless/mediatek/mt76/mt7996/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */ ··· 140 140 hif2 = mt7996_pci_init_hif2(pdev); 141 141 dev->hif2 = hif2; 142 142 143 + mt76_npu_init(mdev, pci_resource_start(pdev, 0), 144 + pdev->bus && pci_domain_nr(pdev->bus) ? 3 : 2); 145 + 143 146 ret = mt7996_mmio_wed_init(dev, pdev, false, &irq); 144 147 if (ret < 0) 145 148 goto free_wed_or_irq_vector; ··· 161 158 goto free_wed_or_irq_vector; 162 159 163 160 mt76_wr(dev, MT_INT_MASK_CSR, 0); 164 - /* master switch of PCIe tnterrupt enable */ 161 + /* master switch of PCIe interrupt enable */ 165 162 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 166 163 167 164 if (hif2) {
+1 -1
drivers/net/wireless/mediatek/mt76/mt7996/regs.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2022 MediaTek Inc. 4 4 */
+501
drivers/net/wireless/mediatek/mt76/npu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2025 AIROHA Inc 4 + * Author: Lorenzo Bianconi <lorenzo@kernel.org> 5 + */ 6 + #include <linux/kernel.h> 7 + #include <net/flow_offload.h> 8 + #include <net/pkt_cls.h> 9 + 10 + #include "mt76.h" 11 + #include "dma.h" 12 + #include "mt76_connac.h" 13 + 14 + #define MT76_NPU_RX_BUF_SIZE (1800 + \ 15 + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) 16 + 17 + int mt76_npu_fill_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) 18 + { 19 + int nframes = 0; 20 + 21 + while (q->queued < q->ndesc - 1) { 22 + struct airoha_npu_rx_dma_desc *desc = (void *)q->desc; 23 + struct mt76_queue_entry *e = &q->entry[q->head]; 24 + struct page *page; 25 + int offset; 26 + 27 + e->buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); 28 + if (!e->buf) 29 + break; 30 + 31 + e->dma_len[0] = SKB_WITH_OVERHEAD(q->buf_size); 32 + page = virt_to_head_page(e->buf); 33 + e->dma_addr[0] = page_pool_get_dma_addr(page) + offset; 34 + 35 + memset(&desc[q->head], 0, sizeof(*desc)); 36 + desc[q->head].addr = e->dma_addr[0]; 37 + 38 + q->head = (q->head + 1) % q->ndesc; 39 + q->queued++; 40 + nframes++; 41 + } 42 + 43 + return nframes; 44 + } 45 + 46 + void mt76_npu_queue_cleanup(struct mt76_dev *dev, struct mt76_queue *q) 47 + { 48 + spin_lock_bh(&q->lock); 49 + while (q->queued > 0) { 50 + struct mt76_queue_entry *e = &q->entry[q->tail]; 51 + 52 + dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0], 53 + e->dma_len[0], 54 + page_pool_get_dma_dir(q->page_pool)); 55 + mt76_put_page_pool_buf(e->buf, false); 56 + q->tail = (q->tail + 1) % q->ndesc; 57 + q->queued--; 58 + } 59 + spin_unlock_bh(&q->lock); 60 + } 61 + 62 + static struct sk_buff *mt76_npu_dequeue(struct mt76_dev *dev, 63 + struct mt76_queue *q, 64 + u32 *info) 65 + { 66 + struct airoha_npu_rx_dma_desc *desc = (void *)q->desc; 67 + int i, nframes, index = q->tail; 68 + struct sk_buff *skb = NULL; 69 + 70 + nframes = FIELD_GET(NPU_RX_DMA_PKT_COUNT_MASK, desc[index].info); 71 + nframes = max_t(int, nframes, 1); 72 + 73 + for (i = 0; i < nframes; i++) { 74 + struct mt76_queue_entry *e = &q->entry[index]; 75 + int len = FIELD_GET(NPU_RX_DMA_DESC_CUR_LEN_MASK, 76 + desc[index].ctrl); 77 + 78 + if (!FIELD_GET(NPU_RX_DMA_DESC_DONE_MASK, desc[index].ctrl)) { 79 + dev_kfree_skb(skb); 80 + return NULL; 81 + } 82 + 83 + dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0], 84 + e->dma_len[0], 85 + page_pool_get_dma_dir(q->page_pool)); 86 + 87 + if (!skb) { 88 + skb = napi_build_skb(e->buf, q->buf_size); 89 + if (!skb) 90 + return NULL; 91 + 92 + __skb_put(skb, len); 93 + skb_reset_mac_header(skb); 94 + skb_mark_for_recycle(skb); 95 + } else { 96 + struct skb_shared_info *shinfo = skb_shinfo(skb); 97 + struct page *page = virt_to_head_page(e->buf); 98 + int nr_frags = shinfo->nr_frags; 99 + 100 + if (nr_frags < ARRAY_SIZE(shinfo->frags)) 101 + skb_add_rx_frag(skb, nr_frags, page, 102 + e->buf - page_address(page), 103 + len, q->buf_size); 104 + } 105 + 106 + *info = desc[index].info; 107 + index = (index + 1) % q->ndesc; 108 + } 109 + q->tail = index; 110 + q->queued -= i; 111 + Q_WRITE(q, dma_idx, q->tail); 112 + 113 + return skb; 114 + } 115 + 116 + void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb, 117 + u32 info) 118 + { 119 + struct airoha_ppe_dev *ppe_dev; 120 + u16 reason, hash; 121 + 122 + if (!mt76_npu_device_active(dev)) 123 + return; 124 + 125 + rcu_read_lock(); 126 + 127 + ppe_dev = rcu_dereference(dev->mmio.ppe_dev); 128 + if (!ppe_dev) 129 + goto out; 130 + 131 + hash = FIELD_GET(NPU_RX_DMA_FOE_ID_MASK, info); 132 + skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); 133 + 134 + reason = FIELD_GET(NPU_RX_DMA_CRSN_MASK, info); 135 + if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { 136 + skb_set_mac_header(skb, 0); 137 + airoha_ppe_dev_check_skb(ppe_dev, skb, hash, true); 138 + } 139 + out: 140 + rcu_read_unlock(); 141 + } 142 + EXPORT_SYMBOL_GPL(mt76_npu_check_ppe); 143 + 144 + static int mt76_npu_rx_poll(struct napi_struct *napi, int budget) 145 + { 146 + struct mt76_dev *dev = mt76_priv(napi->dev); 147 + enum mt76_rxq_id qid = napi - dev->napi; 148 + struct airoha_npu *npu; 149 + int done = 0; 150 + 151 + rcu_read_lock(); 152 + 153 + npu = rcu_dereference(dev->mmio.npu); 154 + if (!npu) 155 + goto out; 156 + 157 + while (done < budget) { 158 + struct sk_buff *skb; 159 + u32 info = 0; 160 + 161 + skb = mt76_npu_dequeue(dev, &dev->q_rx[qid], &info); 162 + if (!skb) 163 + break; 164 + 165 + dev->drv->rx_skb(dev, qid, skb, &info); 166 + mt76_rx_poll_complete(dev, qid, napi); 167 + done++; 168 + } 169 + 170 + mt76_npu_fill_rx_queue(dev, &dev->q_rx[qid]); 171 + out: 172 + if (done < budget && napi_complete(napi)) 173 + dev->drv->rx_poll_complete(dev, qid); 174 + 175 + rcu_read_unlock(); 176 + 177 + return done; 178 + } 179 + 180 + static irqreturn_t mt76_npu_irq_handler(int irq, void *q_instance) 181 + { 182 + struct mt76_queue *q = q_instance; 183 + struct mt76_dev *dev = q->dev; 184 + int qid = q - &dev->q_rx[0]; 185 + int index = qid - MT_RXQ_NPU0; 186 + struct airoha_npu *npu; 187 + u32 status; 188 + 189 + rcu_read_lock(); 190 + 191 + npu = rcu_dereference(dev->mmio.npu); 192 + if (!npu) 193 + goto out; 194 + 195 + status = airoha_npu_wlan_get_irq_status(npu, index); 196 + airoha_npu_wlan_set_irq_status(npu, status); 197 + 198 + airoha_npu_wlan_disable_irq(npu, index); 199 + napi_schedule(&dev->napi[qid]); 200 + out: 201 + rcu_read_unlock(); 202 + 203 + return IRQ_HANDLED; 204 + } 205 + 206 + int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q, 207 + struct sk_buff *skb, struct mt76_queue_buf *buf, 208 + void *txwi_ptr) 209 + { 210 + u16 txwi_len = min_t(u16, phy->dev->drv->txwi_size, NPU_TXWI_LEN); 211 + struct airoha_npu_tx_dma_desc *desc = (void *)q->desc; 212 + int ret; 213 + 214 + /* TODO: Take into account unlinear skbs */ 215 + memcpy(desc[q->head].txwi, txwi_ptr, txwi_len); 216 + desc[q->head].addr = buf->addr; 217 + desc[q->head].ctrl = FIELD_PREP(NPU_TX_DMA_DESC_VEND_LEN_MASK, txwi_len) | 218 + FIELD_PREP(NPU_TX_DMA_DESC_LEN_MASK, skb->len) | 219 + NPU_TX_DMA_DESC_DONE_MASK; 220 + 221 + ret = q->head; 222 + q->entry[q->head].skip_buf0 = true; 223 + q->entry[q->head].skip_buf1 = true; 224 + q->entry[q->head].txwi = NULL; 225 + q->entry[q->head].skb = NULL; 226 + q->entry[q->head].wcid = 0xffff; 227 + 228 + q->head = (q->head + 1) % q->ndesc; 229 + q->queued++; 230 + 231 + return ret; 232 + } 233 + 234 + void mt76_npu_txdesc_cleanup(struct mt76_queue *q, int index) 235 + { 236 + struct airoha_npu_tx_dma_desc *desc = (void *)q->desc; 237 + 238 + if (!mt76_queue_is_npu_tx(q)) 239 + return; 240 + 241 + desc[index].ctrl &= ~NPU_TX_DMA_DESC_DONE_MASK; 242 + } 243 + 244 + void mt76_npu_queue_setup(struct mt76_dev *dev, struct mt76_queue *q) 245 + { 246 + int qid = FIELD_GET(MT_QFLAG_WED_RING, q->flags); 247 + bool xmit = mt76_queue_is_npu_tx(q); 248 + struct airoha_npu *npu; 249 + 250 + if (!mt76_queue_is_npu(q)) 251 + return; 252 + 253 + npu = rcu_dereference_protected(dev->mmio.npu, &dev->mutex); 254 + if (npu) 255 + q->wed_regs = airoha_npu_wlan_get_queue_addr(npu, qid, xmit); 256 + } 257 + 258 + int mt76_npu_rx_queue_init(struct mt76_dev *dev, struct mt76_queue *q) 259 + { 260 + int err, irq, qid = q - &dev->q_rx[0]; 261 + int size, index = qid - MT_RXQ_NPU0; 262 + struct airoha_npu *npu; 263 + const char *name; 264 + 265 + mutex_lock(&dev->mutex); 266 + 267 + npu = rcu_dereference_protected(dev->mmio.npu, &dev->mutex); 268 + irq = npu && index < ARRAY_SIZE(npu->irqs) ? npu->irqs[index] 269 + : -EINVAL; 270 + if (irq < 0) { 271 + err = irq; 272 + goto out; 273 + } 274 + 275 + q->flags = MT_NPU_Q_RX(index); 276 + size = qid == MT_RXQ_NPU1 ? NPU_RX1_DESC_NUM : NPU_RX0_DESC_NUM; 277 + err = dev->queue_ops->alloc(dev, q, 0, size, 278 + MT76_NPU_RX_BUF_SIZE, 0); 279 + if (err) 280 + goto out; 281 + 282 + name = devm_kasprintf(dev->dev, GFP_KERNEL, "mt76-npu.%d", index); 283 + if (!name) { 284 + err = -ENOMEM; 285 + goto out; 286 + } 287 + 288 + err = devm_request_irq(dev->dev, irq, mt76_npu_irq_handler, 289 + IRQF_SHARED, name, q); 290 + if (err) 291 + goto out; 292 + 293 + netif_napi_add(dev->napi_dev, &dev->napi[qid], mt76_npu_rx_poll); 294 + mt76_npu_fill_rx_queue(dev, q); 295 + napi_enable(&dev->napi[qid]); 296 + out: 297 + mutex_unlock(&dev->mutex); 298 + 299 + return err; 300 + } 301 + EXPORT_SYMBOL_GPL(mt76_npu_rx_queue_init); 302 + 303 + static int mt76_npu_setup_tc_block_cb(enum tc_setup_type type, 304 + void *type_data, void *cb_priv) 305 + { 306 + struct mt76_phy *phy = cb_priv; 307 + struct mt76_dev *dev = phy->dev; 308 + struct airoha_ppe_dev *ppe_dev; 309 + int err = -EOPNOTSUPP; 310 + 311 + if (type != TC_SETUP_CLSFLOWER) 312 + return -EOPNOTSUPP; 313 + 314 + mutex_lock(&dev->mutex); 315 + 316 + ppe_dev = rcu_dereference_protected(dev->mmio.ppe_dev, &dev->mutex); 317 + if (ppe_dev) 318 + err = airoha_ppe_dev_setup_tc_block_cb(ppe_dev, type_data); 319 + 320 + mutex_unlock(&dev->mutex); 321 + 322 + return err; 323 + } 324 + 325 + static int mt76_npu_setup_tc_block(struct mt76_phy *phy, 326 + struct net_device *dev, 327 + struct flow_block_offload *f) 328 + { 329 + flow_setup_cb_t *cb = mt76_npu_setup_tc_block_cb; 330 + static LIST_HEAD(block_cb_list); 331 + struct flow_block_cb *block_cb; 332 + 333 + if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) 334 + return -EOPNOTSUPP; 335 + 336 + if (!tc_can_offload(dev)) 337 + return -EOPNOTSUPP; 338 + 339 + f->driver_block_list = &block_cb_list; 340 + switch (f->command) { 341 + case FLOW_BLOCK_BIND: 342 + block_cb = flow_block_cb_lookup(f->block, cb, dev); 343 + if (block_cb) { 344 + flow_block_cb_incref(block_cb); 345 + return 0; 346 + } 347 + 348 + block_cb = flow_block_cb_alloc(cb, dev, phy, NULL); 349 + if (IS_ERR(block_cb)) 350 + return PTR_ERR(block_cb); 351 + 352 + flow_block_cb_incref(block_cb); 353 + flow_block_cb_add(block_cb, f); 354 + list_add_tail(&block_cb->driver_list, &block_cb_list); 355 + return 0; 356 + case FLOW_BLOCK_UNBIND: 357 + block_cb = flow_block_cb_lookup(f->block, cb, dev); 358 + if (!block_cb) 359 + return -ENOENT; 360 + 361 + if (!flow_block_cb_decref(block_cb)) { 362 + flow_block_cb_remove(block_cb, f); 363 + list_del(&block_cb->driver_list); 364 + } 365 + return 0; 366 + default: 367 + return -EOPNOTSUPP; 368 + } 369 + } 370 + 371 + int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 372 + struct net_device *dev, enum tc_setup_type type, 373 + void *type_data) 374 + { 375 + struct mt76_phy *phy = hw->priv; 376 + 377 + if (!tc_can_offload(dev)) 378 + return -EOPNOTSUPP; 379 + 380 + if (!mt76_npu_device_active(phy->dev)) 381 + return -EOPNOTSUPP; 382 + 383 + switch (type) { 384 + case TC_SETUP_BLOCK: 385 + case TC_SETUP_FT: 386 + return mt76_npu_setup_tc_block(phy, dev, type_data); 387 + default: 388 + return -EOPNOTSUPP; 389 + } 390 + } 391 + EXPORT_SYMBOL_GPL(mt76_npu_net_setup_tc); 392 + 393 + void mt76_npu_disable_irqs(struct mt76_dev *dev) 394 + { 395 + struct airoha_npu *npu; 396 + int i; 397 + 398 + rcu_read_lock(); 399 + 400 + npu = rcu_dereference(dev->mmio.npu); 401 + if (!npu) 402 + goto unlock; 403 + 404 + for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++) { 405 + int qid = i - MT_RXQ_NPU0; 406 + u32 status; 407 + 408 + status = airoha_npu_wlan_get_irq_status(npu, qid); 409 + airoha_npu_wlan_set_irq_status(npu, status); 410 + airoha_npu_wlan_disable_irq(npu, qid); 411 + } 412 + unlock: 413 + rcu_read_unlock(); 414 + } 415 + EXPORT_SYMBOL_GPL(mt76_npu_disable_irqs); 416 + 417 + int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type) 418 + { 419 + struct airoha_ppe_dev *ppe_dev; 420 + struct airoha_npu *npu; 421 + int err = 0; 422 + 423 + /* NPU offloading is only supported by MT7992 */ 424 + if (!is_mt7992(dev)) 425 + return 0; 426 + 427 + mutex_lock(&dev->mutex); 428 + 429 + npu = airoha_npu_get(dev->dev); 430 + if (IS_ERR(npu)) { 431 + request_module("airoha-npu"); 432 + npu = airoha_npu_get(dev->dev); 433 + } 434 + 435 + if (IS_ERR(npu)) { 436 + err = PTR_ERR(npu); 437 + goto error_unlock; 438 + } 439 + 440 + ppe_dev = airoha_ppe_get_dev(dev->dev); 441 + if (IS_ERR(ppe_dev)) { 442 + request_module("airoha-eth"); 443 + ppe_dev = airoha_ppe_get_dev(dev->dev); 444 + } 445 + 446 + if (IS_ERR(ppe_dev)) { 447 + err = PTR_ERR(ppe_dev); 448 + goto error_npu_put; 449 + } 450 + 451 + err = airoha_npu_wlan_init_reserved_memory(npu); 452 + if (err) 453 + goto error_ppe_put; 454 + 455 + dev->dma_dev = npu->dev; 456 + dev->mmio.phy_addr = phy_addr; 457 + dev->mmio.npu_type = type; 458 + /* NPU offloading requires HW-RRO for RX packet reordering. */ 459 + dev->hwrro_mode = MT76_HWRRO_V3_1; 460 + 461 + rcu_assign_pointer(dev->mmio.npu, npu); 462 + rcu_assign_pointer(dev->mmio.ppe_dev, ppe_dev); 463 + synchronize_rcu(); 464 + 465 + mutex_unlock(&dev->mutex); 466 + 467 + return 0; 468 + 469 + error_ppe_put: 470 + airoha_ppe_put_dev(ppe_dev); 471 + error_npu_put: 472 + airoha_npu_put(npu); 473 + error_unlock: 474 + mutex_unlock(&dev->mutex); 475 + 476 + return err; 477 + } 478 + EXPORT_SYMBOL_GPL(mt76_npu_init); 479 + 480 + void mt76_npu_deinit(struct mt76_dev *dev) 481 + { 482 + struct airoha_ppe_dev *ppe_dev; 483 + struct airoha_npu *npu; 484 + 485 + mutex_lock(&dev->mutex); 486 + 487 + npu = rcu_replace_pointer(dev->mmio.npu, NULL, 488 + lockdep_is_held(&dev->mutex)); 489 + if (npu) 490 + airoha_npu_put(npu); 491 + 492 + ppe_dev = rcu_replace_pointer(dev->mmio.ppe_dev, NULL, 493 + lockdep_is_held(&dev->mutex)); 494 + if (ppe_dev) 495 + airoha_ppe_put_dev(ppe_dev); 496 + 497 + mutex_unlock(&dev->mutex); 498 + 499 + mt76_npu_queue_cleanup(dev, &dev->q_rx[MT_RXQ_NPU0]); 500 + mt76_npu_queue_cleanup(dev, &dev->q_rx[MT_RXQ_NPU1]); 501 + }
+1 -1
drivers/net/wireless/mediatek/mt76/pci.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/scan.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/sdio.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * This file is written based on mt76/usb.c.
+1 -1
drivers/net/wireless/mediatek/mt76/sdio.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * Author: Sean Wang <sean.wang@mediatek.com>
+1 -1
drivers/net/wireless/mediatek/mt76/sdio_txrx.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 MediaTek Inc. 3 3 * 4 4 * Author: Felix Fietkau <nbd@nbd.name>
+1 -1
drivers/net/wireless/mediatek/mt76/testmode.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */ 3 3 4 4 #include <linux/random.h>
+1 -1
drivers/net/wireless/mediatek/mt76/testmode.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/trace.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/trace.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+5 -3
drivers/net/wireless/mediatek/mt76/tx.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */ ··· 847 847 848 848 spin_lock_bh(&dev->token_lock); 849 849 850 - token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC); 851 - if (token >= 0) 850 + token = idr_alloc(&dev->token, *ptxwi, dev->token_start, 851 + dev->token_start + dev->token_size, 852 + GFP_ATOMIC); 853 + if (token >= dev->token_start) 852 854 dev->token_count++; 853 855 854 856 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+1 -1
drivers/net/wireless/mediatek/mt76/usb.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/usb_trace.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/usb_trace.h
··· 1 - /* SPDX-License-Identifier: ISC */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 4 */
+1 -1
drivers/net/wireless/mediatek/mt76/util.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 4 */
+1 -2
drivers/net/wireless/mediatek/mt76/util.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 1 + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2 2 /* 3 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 - * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> 5 4 */ 6 5 7 6 #ifndef __MT76_UTIL_H
+6 -6
drivers/net/wireless/mediatek/mt76/wed.c
··· 1 - // SPDX-License-Identifier: ISC 1 + // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org> 4 4 */ ··· 8 8 9 9 void mt76_wed_release_rx_buf(struct mtk_wed_device *wed) 10 10 { 11 - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); 11 + struct mt76_dev *dev = mt76_wed_to_dev(wed); 12 12 int i; 13 13 14 14 for (i = 0; i < dev->rx_token_size; i++) { ··· 31 31 #ifdef CONFIG_NET_MEDIATEK_SOC_WED 32 32 u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size) 33 33 { 34 - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); 35 34 struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc; 35 + struct mt76_dev *dev = mt76_wed_to_dev(wed); 36 36 struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; 37 37 struct mt76_txwi_cache *t = NULL; 38 38 int i; ··· 80 80 81 81 int mt76_wed_offload_enable(struct mtk_wed_device *wed) 82 82 { 83 - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); 83 + struct mt76_dev *dev = mt76_wed_to_dev(wed); 84 84 85 85 spin_lock_bh(&dev->token_lock); 86 86 dev->token_size = wed->wlan.token_start; ··· 164 164 165 165 void mt76_wed_offload_disable(struct mtk_wed_device *wed) 166 166 { 167 - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); 167 + struct mt76_dev *dev = mt76_wed_to_dev(wed); 168 168 169 169 spin_lock_bh(&dev->token_lock); 170 170 dev->token_size = dev->drv->token_size; ··· 174 174 175 175 void mt76_wed_reset_complete(struct mtk_wed_device *wed) 176 176 { 177 - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); 177 + struct mt76_dev *dev = mt76_wed_to_dev(wed); 178 178 179 179 complete(&dev->mmio.wed_reset_complete); 180 180 }
+1
include/linux/soc/airoha/airoha_offload.h
··· 6 6 #ifndef AIROHA_OFFLOAD_H 7 7 #define AIROHA_OFFLOAD_H 8 8 9 + #include <linux/skbuff.h> 9 10 #include <linux/spinlock.h> 10 11 #include <linux/workqueue.h> 11 12
+1
include/linux/soc/mediatek/mtk_wed.h
··· 154 154 bool wcid_512; 155 155 bool hw_rro; 156 156 bool msi; 157 + bool hif2; 157 158 158 159 u16 token_start; 159 160 unsigned int nbuf;