From 7a26c298a225e23e33d406537853c75bc239ff2c Mon Sep 17 00:00:00 2001 From: actions-user Date: Mon, 3 Nov 2025 00:55:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 398 ++++++ ath.mk | 435 ++++++ broadcom.mk | 497 +++++++ intel.mk | 78 ++ marvell.mk | 51 + patches/ath/070-ath_common_config.patch | 10 + patches/ath/400-ath_move_debug_code.patch | 31 + patches/ath/402-ath_regd_optional.patch | 92 ++ patches/ath/403-world_regd_fixup.patch | 84 ++ patches/ath/404-regd_no_assoc_hints.patch | 19 + patches/ath/405-ath_regd_us.patch | 26 + patches/ath/406-ath_relax_default_regd.patch | 51 + ...add_platform_eeprom_support_to_ath5k.patch | 56 + .../ath10k/080-ath10k_thermal_config.patch | 47 + ...21-ath10k_init_devices_synchronously.patch | 33 + .../930-ath10k_add_tpt_led_trigger.patch | 37 + ...75-ath10k-use-tpt-trigger-by-default.patch | 51 + ...-power-reduction-for-US-regulatory-d.patch | 101 ++ ...isable-caldata-prefetch-for-sdio-bus.patch | 24 + .../ath10k/983-ath10k-allow-vht-on-2g.patch | 10 + ...h10k-Try-to-get-mac-address-from-dts.patch | 37 + ...k-always-use-mac80211-loss-detection.patch | 28 + patches/ath10k/990-ath10k-small-buffers.patch | 64 + .../991-ath10k-support-flush_sta-method.patch | 70 + ...i-ath11k-use-unique-QRTR-instance-ID.patch | 164 +++ ...ort-setting-bdf-addr-and-caldb-addr-.patch | 62 + ...k-control-thermal-support-via-symbol.patch | 66 + ...upport-setting-FW-memory-mode-via-DT.patch | 75 ++ ...tersection-support-for-regulatory-ru.patch | 332 +++++ ...-ath11k-disable-coldboot-for-ipq6018.patch | 26 + ...ble-coldboot-calibration-for-ipq5018.patch | 27 + ...apped-ce-accessing-issue-on-64bit-OS.patch | 153 +++ ...ifi-ath11k-add-hw-params-for-QCN6122.patch | 120 ++ ...wifi-ath11k-add-hal-regs-for-QCN6122.patch | 114 ++ ...-ath11k-add-hw-ring-mask-for-QCN6122.patch | 74 ++ ...k-update-hif_and-pci_ops-for-QCN6122.patch | 102 ++ ...h11k-add-multipd-support-for-QCN6122.patch | 110 ++ ...fi-ath11k-add-QCN6122-device-support.patch | 55 + ...11k-Support-to-assign-m3-dump-memory.patch | 31 + ...-wifi-ath11k-poll-reo-status-ipq5018.patch | 164 +++ ...alized_flag_for_deinit-ed_srng_lists.patch | 92 ++ ...ic_in_ath11k_mac_op_set_bitrate_mask.patch | 67 + ...h11k-fix_dest_ring-buffer_corruption.patch | 83 ++ ...1k-fix_source_ring-buffer_corruption.patch | 56 + ...-buffer_corruption_when_ring_is_full.patch | 61 + ...group_data_packet_drops_during_rekey.patch | 237 ++++ ...LL_dereference_in_ath11k_qmi_m3_load.patch | 40 + .../ath11k/983-ath11k-Enable-VHT-for-2G.patch | 35 + ...84-ath11k-workaround-for-memory-leak.patch | 13 + ...0-ath12k-prevent-ltssm-startup-crash.patch | 17 + ...k-limit-WMI_SCAN_CHAN_LIST_CMDID-arg.patch | 153 +++ ...k-fix-5GHz-operation-on-wideband-QCN.patch | 137 ++ ...k-push-HE-MU-MIMO-params-to-hardware.patch | 484 +++++++ ...-push-EHT-MU-MIMO-params-to-hardware.patch | 242 ++++ ...HE-MCS-mapper-to-a-separate-function.patch | 173 +++ ...and-tx-mcs-maps-for-supported-HE-mcs.patch | 197 +++ ...X-MCS-rate-configurations-in-HE-mode.patch | 152 +++ ...ort-for-setting-fixed-HE-rate-GI-LTF.patch | 1184 +++++++++++++++++ ...7-wifi-ath12k-clean-up-80P80-support.patch | 262 ++++ ...2k-add-support-for-160-MHz-bandwidth.patch | 379 ++++++ ...ed-NSS-bandwidth-support-for-160-MHz.patch | 202 +++ ...2k-convert-tasklet-to-BH-workqueue-f.patch | 82 ++ .../201-ath5k-WAR-for-AR71xx-PCI-bug.patch | 38 + .../ath5k/411-ath5k_allow_adhoc_and_ap.patch | 46 + patches/ath5k/420-ath5k_disable_fast_cc.patch | 18 + patches/ath5k/430-add_ath5k_platform.patch | 33 + .../ath5k/440-ath5k_channel_bw_debugfs.patch | 142 ++ .../341-wifi-ath9k-obtain-system-gpios.patch | 273 ++++ ...w-reset-AHB-WMAC-interface-on-AR91xx.patch | 25 + ..._hw-issue-external-reset-for-QCA955x.patch | 129 ++ ...h9k-force-rx_clear-when-disabling-rx.patch | 35 + ...erpret-requested-txpower-in-EIRP-dom.patch | 36 + ...power-reduction-for-US-regulatory-do.patch | 24 + patches/ath9k/401-ath9k_blink_default.patch | 11 + .../ath9k/410-ath9k_allow_adhoc_and_ap.patch | 10 + ...abled-MFP-capability-unconditionally.patch | 34 + patches/ath9k/500-ath9k_eeprom_debugfs.patch | 92 ++ patches/ath9k/501-ath9k_ahb_init.patch | 34 + .../510-ath9k_intr_mitigation_tweak.patch | 18 + patches/ath9k/511-ath9k_reduce_rxbuf.patch | 11 + .../ath9k/512-ath9k_channelbw_debugfs.patch | 191 +++ patches/ath9k/513-ath9k_add_pci_ids.patch | 30 + patches/ath9k/530-ath9k_extra_leds.patch | 267 ++++ .../ath9k/540-ath9k_reduce_ani_interval.patch | 11 + patches/ath9k/542-ath9k_debugfs_diag.patch | 139 ++ .../ath9k/543-ath9k_entropy_from_adc.patch | 186 +++ ...544-ath9k-ar933x-usb-hang-workaround.patch | 79 ++ patches/ath9k/545-ath9k_ani_ws_detect.patch | 155 +++ .../ath9k/547-ath9k_led_defstate_fix.patch | 29 + .../ath9k/548-ath9k_enable_gpio_chip.patch | 210 +++ patches/ath9k/550-ath9k-of.patch | 166 +++ .../ath9k/551-ath9k_ubnt_uap_plus_hsr.patch | 406 ++++++ patches/ath9k/552-ath9k-ahb_of.patch | 100 ++ patches/brcm/040-brcmutil_option.patch | 10 + .../810-b43-gpio-mask-module-option.patch | 37 + patches/brcm/811-b43_no_pio.patch | 86 ++ .../brcm/812-b43-add-antenna-control.patch | 131 ++ .../813-b43-reduce-number-of-RX-slots.patch | 11 + .../814-b43-only-use-gpio-0-1-for-led.patch | 17 + ...815-b43-always-take-overlapping-devs.patch | 11 + ...-remove-extra-regulation-restriction.patch | 27 + ...und-bug-with-some-inconsistent-BSSes.patch | 49 + ...-in-driver-tables-with-country-codes.patch | 60 + ...mfmac-adds-support-for-BCM43341-wifi.patch | 29 + ...fer-a-ccode-from-OTP-over-nvram-file.patch | 130 ++ ...ac-Increase-power-saving-delay-to-2s.patch | 24 + ...upport-DS1-exit-firmware-re-download.patch | 721 ++++++++++ ...eroperating-DPP-and-other-encryption.patch | 129 ++ ...c-Include-modinfo-for-43456-CLM-blob.patch | 26 + ...mfmac-disable-dump_survey-on-bcm2835.patch | 38 + patches/build/000-fix_kconfig.patch | 14 + patches/build/001-fix_build.patch | 168 +++ patches/build/002-change_allconfig.patch | 64 + .../build/003-remove_bogus_modparams.patch | 34 + patches/build/004-fix-kconf-compiling.patch | 47 + patches/build/005-fix-kconf-warnings.patch | 76 ++ patches/build/012-kernel_build_check.patch | 11 + patches/build/020-intel-mld-compile.patch | 54 + .../100-backports-drop-QRTR-and-MHI.patch | 76 ++ ...port-fix-unaligned.h-header-location.patch | 26 + patches/build/140-trace_backport.patch | 694 ++++++++++ .../150-ath_iommu_paging_domain_revert.patch | 32 + .../build/200-iwlwifi_thermal_backport.patch | 40 + .../210-wireless_netns_local_backport.patch | 55 + .../220-brcmfmac_usb_driver_backport.patch | 14 + ...x-init_vqs-build-error-on-kernel-6.6.patch | 30 + .../240-realtek-rtw88-BH-workqueue.patch | 14 + ...-genlmsg_multicast_allns-upstream-ba.patch | 121 ++ .../build/360-change-read_new-to-read.patch | 20 + .../build/400-restore-old-debugfs_fops.patch | 252 ++++ ...-convert-short-fops-to-debugfs-files.patch | 210 +++ ...01-wifi-mt7601u-update-firmware-path.patch | 55 + ...100-w1fi-mt7601u-Add-AP-mode-support.patch | 36 + ...700-mwl8k-missing-pci-id-for-WNR854T.patch | 10 + .../801-libertas-configure-sysfs-links.patch | 21 + .../802-libertas-set-wireless-macaddr.patch | 11 + ...crease-the-global-limit-up-to-4-SSID.patch | 41 + ...940-mwl8k_init_devices_synchronously.patch | 20 + ...ringified-name-of-command-in-error-l.patch | 177 +++ patches/rt2x00/100-rt2x00_options.patch | 47 + ...to-build-rt2800soc-module-for-RT3883.patch | 30 + ...support-for-loading-EEPROM-from-user.patch | 228 ++++ ...-support-for-loading-EEPROM-from-MTD.patch | 108 ++ ...i-rt2x00-Support-EEPROM-swap-binding.patch | 44 + ...port-loading-eeprom-from-NVMEM-cells.patch | 96 ++ ...EEPROM-from-devicetree-embedded-data.patch | 76 ++ ...00-allow_disabling_bands_through_dts.patch | 17 + ...c-loadable-via-OF-on-rt288x-305x-SoC.patch | 34 + ...0-rt2x00-change-led-polarity-from-OF.patch | 40 + .../611-rt2x00-add-AP+STA-support.patch | 11 + ...spect-rt2800-hardware-TX-queue-index.patch | 257 ++++ ...ease-the-watchdog-sampling-frequency.patch | 74 ++ ...librate-MT7620-when-switching-channe.patch | 77 ++ ...-rt2x00-rework-link-tuner-for-MT7620.patch | 48 + ...rrect-MT7620-SDM-mode-register-value.patch | 25 + ...gister-operation-on-RXIQ-calibration.patch | 26 + ...FCSR-register-init-values-for-RT5592.patch | 230 ++++ ...-BBP-register-init-values-for-RT5592.patch | 119 ++ ...t-support-for-external-LNA-on-MT7620.patch | 121 ++ ...duce-accessors-for-CHIP_VER-register.patch | 139 ++ ...-differentiate-based-on-SoC-CHIP_VER.patch | 437 ++++++ .../110-mac80211_keep_keys_on_stop_ap.patch | 24 + .../120-cfg80211_allow_perm_addr_change.patch | 52 + patches/subsys/130-disable_auto_vif.patch | 27 + patches/subsys/210-ap_scan.patch | 19 + patches/subsys/220-allow-ibss-mixed.patch | 40 + .../230-avoid-crashing-missing-band.patch | 34 + ...domize-BA-session-dialog-token-alloc.patch | 38 + ...-minstrel_ht-fix-MINSTREL_FRAC-macro.patch | 21 + ...l_ht-reduce-fluctuations-in-rate-pro.patch | 30 + ...l_ht-rework-rate-downgrade-code-and-.patch | 151 +++ ...crease-quantum-for-airtime-scheduler.patch | 53 + ...race-period-for-DFS-available-after-.patch | 153 +++ ...dd-AQL-support-for-broadcast-packets.patch | 293 ++++ ...ac80211-Do-not-schedule-stopped-TXQs.patch | 36 + ...n-t-call-fq_flow_idx-for-management-.patch | 33 + ...eck-802.11-encaps-offloading-in-ieee.patch | 32 + ...80211-Update-skb-s-control-block-key.patch | 27 + ...d-link-iteration-macro-for-link-data.patch | 44 + ...211-extend-beacon-monitoring-for-MLO.patch | 85 ++ ...extend-connection-monitoring-for-MLO.patch | 136 ++ ...ke-CONNECTION_MONITOR-optional-for-M.patch | 25 + ...llow-scanning-while-on-radar-channel.patch | 372 ++++++ ...out-part-of-ieee80211_calc_expected_.patch | 140 ++ ...e-expected-throughput-if-not-provide.patch | 53 + ...d-MLO-support-to-ieee80211_probe_cli.patch | 64 + .../subsys/600-mac80211-allow-vht-on-2g.patch | 36 + ralink.mk | 146 ++ realtek.mk | 590 ++++++++ scripts/import-backports.sh | 109 ++ 190 files changed, 20437 insertions(+) create mode 100644 Makefile create mode 100644 ath.mk create mode 100644 broadcom.mk create mode 100644 intel.mk create mode 100644 marvell.mk create mode 100644 patches/ath/070-ath_common_config.patch create mode 100644 patches/ath/400-ath_move_debug_code.patch create mode 100644 patches/ath/402-ath_regd_optional.patch create mode 100644 patches/ath/403-world_regd_fixup.patch create mode 100644 patches/ath/404-regd_no_assoc_hints.patch create mode 100644 patches/ath/405-ath_regd_us.patch create mode 100644 patches/ath/406-ath_relax_default_regd.patch create mode 100644 patches/ath/431-add_platform_eeprom_support_to_ath5k.patch create mode 100644 patches/ath10k/080-ath10k_thermal_config.patch create mode 100644 patches/ath10k/921-ath10k_init_devices_synchronously.patch create mode 100644 patches/ath10k/930-ath10k_add_tpt_led_trigger.patch create mode 100644 patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch create mode 100644 patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch create mode 100644 patches/ath10k/982-ath10k-disable-caldata-prefetch-for-sdio-bus.patch create mode 100644 patches/ath10k/983-ath10k-allow-vht-on-2g.patch create mode 100644 patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch create mode 100644 patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch create mode 100644 patches/ath10k/990-ath10k-small-buffers.patch create mode 100644 patches/ath10k/991-ath10k-support-flush_sta-method.patch create mode 100644 patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch create mode 100644 patches/ath11k/201-wifi-ath11k-Support-setting-bdf-addr-and-caldb-addr-.patch create mode 100644 patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch create mode 100644 patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch create mode 100644 patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch create mode 100644 patches/ath11k/906-wifi-ath11k-disable-coldboot-for-ipq6018.patch create mode 100644 patches/ath11k/907-wifi-ath11k-disable-coldboot-calibration-for-ipq5018.patch create mode 100644 patches/ath11k/910-ath11k-fix-remapped-ce-accessing-issue-on-64bit-OS.patch create mode 100644 patches/ath11k/920-wifi-ath11k-add-hw-params-for-QCN6122.patch create mode 100644 patches/ath11k/921-wifi-ath11k-add-hal-regs-for-QCN6122.patch create mode 100644 patches/ath11k/922-wifi-ath11k-add-hw-ring-mask-for-QCN6122.patch create mode 100644 patches/ath11k/923-wifi-ath11k-update-hif_and-pci_ops-for-QCN6122.patch create mode 100644 patches/ath11k/924-wifi-ath11k-add-multipd-support-for-QCN6122.patch create mode 100644 patches/ath11k/925-wifi-ath11k-add-QCN6122-device-support.patch create mode 100644 patches/ath11k/931-wifi-ath11k-Support-to-assign-m3-dump-memory.patch create mode 100644 patches/ath11k/932-wifi-ath11k-poll-reo-status-ipq5018.patch create mode 100644 patches/ath11k/940-ath11k-clear_initialized_flag_for_deinit-ed_srng_lists.patch create mode 100644 patches/ath11k/941-ath11k-fix_sleeping-in-atomic_in_ath11k_mac_op_set_bitrate_mask.patch create mode 100644 patches/ath11k/942-ath11k-fix_dest_ring-buffer_corruption.patch create mode 100644 patches/ath11k/943-ath11k-fix_source_ring-buffer_corruption.patch create mode 100644 patches/ath11k/944-ath11k-fix_dest_ring-buffer_corruption_when_ring_is_full.patch create mode 100644 patches/ath11k/945-ath11k-fix_group_data_packet_drops_during_rekey.patch create mode 100644 patches/ath11k/946-ath11k-fix_NULL_dereference_in_ath11k_qmi_m3_load.patch create mode 100644 patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch create mode 100644 patches/ath11k/984-ath11k-workaround-for-memory-leak.patch create mode 100644 patches/ath12k/100-ath12k-prevent-ltssm-startup-crash.patch create mode 100644 patches/ath12k/102-wifi-ath12k-limit-WMI_SCAN_CHAN_LIST_CMDID-arg.patch create mode 100644 patches/ath12k/103-wifi-ath12k-fix-5GHz-operation-on-wideband-QCN.patch create mode 100644 patches/ath12k/104-1-wifi-ath12k-push-HE-MU-MIMO-params-to-hardware.patch create mode 100644 patches/ath12k/104-2-wifi-ath12k-push-EHT-MU-MIMO-params-to-hardware.patch create mode 100644 patches/ath12k/104-3-wifi-ath12k-move-HE-MCS-mapper-to-a-separate-function.patch create mode 100644 patches/ath12k/104-4-wifi-ath12k-generate-rx-and-tx-mcs-maps-for-supported-HE-mcs.patch create mode 100644 patches/ath12k/104-5-wifi-ath12k-fix-TX-and-RX-MCS-rate-configurations-in-HE-mode.patch create mode 100644 patches/ath12k/104-6-wifi-ath12k-add-support-for-setting-fixed-HE-rate-GI-LTF.patch create mode 100644 patches/ath12k/104-7-wifi-ath12k-clean-up-80P80-support.patch create mode 100644 patches/ath12k/104-8-wifi-ath12k-add-support-for-160-MHz-bandwidth.patch create mode 100644 patches/ath12k/104-9-wifi-ath12k-add-extended-NSS-bandwidth-support-for-160-MHz.patch create mode 100644 patches/ath12k/200-Revert-wifi-ath12k-convert-tasklet-to-BH-workqueue-f.patch create mode 100644 patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch create mode 100644 patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch create mode 100644 patches/ath5k/420-ath5k_disable_fast_cc.patch create mode 100644 patches/ath5k/430-add_ath5k_platform.patch create mode 100644 patches/ath5k/440-ath5k_channel_bw_debugfs.patch create mode 100644 patches/ath9k/341-wifi-ath9k-obtain-system-gpios.patch create mode 100644 patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch create mode 100644 patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch create mode 100644 patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch create mode 100644 patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch create mode 100644 patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch create mode 100644 patches/ath9k/401-ath9k_blink_default.patch create mode 100644 patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch create mode 100644 patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch create mode 100644 patches/ath9k/500-ath9k_eeprom_debugfs.patch create mode 100644 patches/ath9k/501-ath9k_ahb_init.patch create mode 100644 patches/ath9k/510-ath9k_intr_mitigation_tweak.patch create mode 100644 patches/ath9k/511-ath9k_reduce_rxbuf.patch create mode 100644 patches/ath9k/512-ath9k_channelbw_debugfs.patch create mode 100644 patches/ath9k/513-ath9k_add_pci_ids.patch create mode 100644 patches/ath9k/530-ath9k_extra_leds.patch create mode 100644 patches/ath9k/540-ath9k_reduce_ani_interval.patch create mode 100644 patches/ath9k/542-ath9k_debugfs_diag.patch create mode 100644 patches/ath9k/543-ath9k_entropy_from_adc.patch create mode 100644 patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch create mode 100644 patches/ath9k/545-ath9k_ani_ws_detect.patch create mode 100644 patches/ath9k/547-ath9k_led_defstate_fix.patch create mode 100644 patches/ath9k/548-ath9k_enable_gpio_chip.patch create mode 100644 patches/ath9k/550-ath9k-of.patch create mode 100644 patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch create mode 100644 patches/ath9k/552-ath9k-ahb_of.patch create mode 100644 patches/brcm/040-brcmutil_option.patch create mode 100644 patches/brcm/810-b43-gpio-mask-module-option.patch create mode 100644 patches/brcm/811-b43_no_pio.patch create mode 100644 patches/brcm/812-b43-add-antenna-control.patch create mode 100644 patches/brcm/813-b43-reduce-number-of-RX-slots.patch create mode 100644 patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch create mode 100644 patches/brcm/815-b43-always-take-overlapping-devs.patch create mode 100644 patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch create mode 100644 patches/brcm/860-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch create mode 100644 patches/brcm/861-brcmfmac-add-in-driver-tables-with-country-codes.patch create mode 100644 patches/brcm/870-01-rpi-6.12-brcmfmac-adds-support-for-BCM43341-wifi.patch create mode 100644 patches/brcm/870-02-rpi-6.12-brcmfmac-Prefer-a-ccode-from-OTP-over-nvram-file.patch create mode 100644 patches/brcm/870-03-rpi-6.12-brcmfmac-Increase-power-saving-delay-to-2s.patch create mode 100644 patches/brcm/870-04-rpi-6.12-brcmfmac-non-upstream-support-DS1-exit-firmware-re-download.patch create mode 100644 patches/brcm/870-05-rpi-6.12-brcmfmac-Fix-interoperating-DPP-and-other-encryption.patch create mode 100644 patches/brcm/870-06-rpi-6.12-brcmfmac-Include-modinfo-for-43456-CLM-blob.patch create mode 100644 patches/brcm/871-brcmfmac-disable-dump_survey-on-bcm2835.patch create mode 100644 patches/build/000-fix_kconfig.patch create mode 100644 patches/build/001-fix_build.patch create mode 100644 patches/build/002-change_allconfig.patch create mode 100644 patches/build/003-remove_bogus_modparams.patch create mode 100644 patches/build/004-fix-kconf-compiling.patch create mode 100644 patches/build/005-fix-kconf-warnings.patch create mode 100644 patches/build/012-kernel_build_check.patch create mode 100644 patches/build/020-intel-mld-compile.patch create mode 100644 patches/build/100-backports-drop-QRTR-and-MHI.patch create mode 100644 patches/build/120-backport-fix-unaligned.h-header-location.patch create mode 100644 patches/build/140-trace_backport.patch create mode 100644 patches/build/150-ath_iommu_paging_domain_revert.patch create mode 100644 patches/build/200-iwlwifi_thermal_backport.patch create mode 100644 patches/build/210-wireless_netns_local_backport.patch create mode 100644 patches/build/220-brcmfmac_usb_driver_backport.patch create mode 100644 patches/build/230-fix-init_vqs-build-error-on-kernel-6.6.patch create mode 100644 patches/build/240-realtek-rtw88-BH-workqueue.patch create mode 100644 patches/build/300-backports-handle-genlmsg_multicast_allns-upstream-ba.patch create mode 100644 patches/build/360-change-read_new-to-read.patch create mode 100644 patches/build/400-restore-old-debugfs_fops.patch create mode 100644 patches/build/410-mac80211-convert-short-fops-to-debugfs-files.patch create mode 100644 patches/mt7601u/001-wifi-mt7601u-update-firmware-path.patch create mode 100644 patches/mt7601u/100-w1fi-mt7601u-Add-AP-mode-support.patch create mode 100644 patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch create mode 100644 patches/mwl/801-libertas-configure-sysfs-links.patch create mode 100644 patches/mwl/802-libertas-set-wireless-macaddr.patch create mode 100644 patches/mwl/900-mwifiex-increase-the-global-limit-up-to-4-SSID.patch create mode 100644 patches/mwl/940-mwl8k_init_devices_synchronously.patch create mode 100644 patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch create mode 100644 patches/rt2x00/100-rt2x00_options.patch create mode 100644 patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch create mode 100644 patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch create mode 100644 patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch create mode 100644 patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch create mode 100644 patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch create mode 100644 patches/rt2x00/603-wifi-rt2x00-Add-support-for-loading-EEPROM-from-devicetree-embedded-data.patch create mode 100644 patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch create mode 100644 patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch create mode 100644 patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch create mode 100644 patches/rt2x00/611-rt2x00-add-AP+STA-support.patch create mode 100644 patches/rt2x00/620-01-rt2x00-respect-rt2800-hardware-TX-queue-index.patch create mode 100644 patches/rt2x00/620-02-rt2x00-increase-the-watchdog-sampling-frequency.patch create mode 100644 patches/rt2x00/621-01-rt2x00-always-calibrate-MT7620-when-switching-channe.patch create mode 100644 patches/rt2x00/621-02-rt2x00-rework-link-tuner-for-MT7620.patch create mode 100644 patches/rt2x00/621-03-rt2x00-correct-MT7620-SDM-mode-register-value.patch create mode 100644 patches/rt2x00/621-04-rt2x00-fix-register-operation-on-RXIQ-calibration.patch create mode 100644 patches/rt2x00/622-01-rt2x00-fix-RFCSR-register-init-values-for-RT5592.patch create mode 100644 patches/rt2x00/622-02-rt2x00-fix-BBP-register-init-values-for-RT5592.patch create mode 100644 patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch create mode 100644 patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch create mode 100644 patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch create mode 100644 patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch create mode 100644 patches/subsys/120-cfg80211_allow_perm_addr_change.patch create mode 100644 patches/subsys/130-disable_auto_vif.patch create mode 100644 patches/subsys/210-ap_scan.patch create mode 100644 patches/subsys/220-allow-ibss-mixed.patch create mode 100644 patches/subsys/230-avoid-crashing-missing-band.patch create mode 100644 patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch create mode 100644 patches/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch create mode 100644 patches/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch create mode 100644 patches/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch create mode 100644 patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch create mode 100644 patches/subsys/310-cfg80211-allow-grace-period-for-DFS-available-after-.patch create mode 100644 patches/subsys/320-mac80211-add-AQL-support-for-broadcast-packets.patch create mode 100644 patches/subsys/330-wifi-mac80211-Do-not-schedule-stopped-TXQs.patch create mode 100644 patches/subsys/331-wifi-mac80211-Don-t-call-fq_flow_idx-for-management-.patch create mode 100644 patches/subsys/332-wifi-mac80211-Check-802.11-encaps-offloading-in-ieee.patch create mode 100644 patches/subsys/333-Reapply-wifi-mac80211-Update-skb-s-control-block-key.patch create mode 100644 patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch create mode 100644 patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch create mode 100644 patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch create mode 100644 patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch create mode 100644 patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch create mode 100644 patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch create mode 100644 patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch create mode 100644 patches/subsys/370-wifi-mac80211-add-MLO-support-to-ieee80211_probe_cli.patch create mode 100644 patches/subsys/600-mac80211-allow-vht-on-2g.patch create mode 100644 ralink.mk create mode 100644 realtek.mk create mode 100755 scripts/import-backports.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..77a88cf --- /dev/null +++ b/Makefile @@ -0,0 +1,398 @@ +# +# Copyright (C) 2007-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=mac80211 + +PKG_VERSION:=6.16 +PKG_RELEASE:=1 +PKG_LICENSE:=GPL-2.0-only +PKG_LICENSE_FILES:=COPYING + +PKG_SOURCE_URL:=@OPENWRT +PKG_HASH:=67f11320509dd18e5e2c58cb81e9f6c7d19b09f5229baa5880ed4dab71c19052 + +PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(BUILD_VARIANT),$(PKG_NAME)-$(BUILD_VARIANT)/)backports-$(PKG_VERSION) +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Felix Fietkau + +PKG_DRIVERS = \ + mac80211-hwsim \ + mt7601u \ + rsi91x rsi91x-usb rsi91x-sdio\ + wlcore wl12xx wl18xx + +PKG_CONFIG_DEPENDS:= \ + CONFIG_PACKAGE_kmod-mac80211 \ + CONFIG_PACKAGE_CFG80211_TESTMODE \ + CONFIG_PACKAGE_MAC80211_DEBUGFS \ + CONFIG_PACKAGE_MAC80211_MESH \ + CONFIG_PACKAGE_MAC80211_TRACING \ + CONFIG_PACKAGE_IWLWIFI_DEBUG \ + CONFIG_PACKAGE_IWLWIFI_DEBUGFS \ + CONFIG_PACKAGE_RTLWIFI_DEBUG \ + +include $(INCLUDE_DIR)/package.mk + +WMENU:=Wireless Drivers + +define KernelPackage/mac80211/Default + SUBMENU:=$(WMENU) + URL:=https://wireless.wiki.kernel.org/ + MAINTAINER:=Felix Fietkau +endef + +# config_pacakge: +# 1 = OpenWrt KernelPackage name +# 2 = Optional list of variants for which the module may be selected: +# If empty, the module is only selected with the first variant +# Use $(ALL_VARIANTS) to allow module selection in all variants +config_package=$(if $(and $(CONFIG_PACKAGE_kmod-$(1)),$(call mac80211_variant_check,$(2))),m) +mac80211_variant_check=$(if $(ALL_VARIANTS),$(filter $(BUILD_VARIANT),$(if $(1),$(1),$(firstword $(ALL_VARIANTS)))),y) + +config-y:= \ + WLAN \ + CFG80211_CERTIFICATION_ONUS \ + MAC80211_RC_MINSTREL \ + MAC80211_RC_MINSTREL_HT \ + MAC80211_RC_MINSTREL_VHT \ + MAC80211_RC_DEFAULT_MINSTREL \ + WLAN_VENDOR_ADMTEK \ + WLAN_VENDOR_ATH \ + WLAN_VENDOR_ATMEL \ + WLAN_VENDOR_BROADCOM \ + WLAN_VENDOR_CISCO \ + WLAN_VENDOR_INTEL \ + WLAN_VENDOR_INTERSIL \ + WLAN_VENDOR_MARVELL \ + WLAN_VENDOR_MEDIATEK \ + WLAN_VENDOR_RALINK \ + WLAN_VENDOR_REALTEK \ + WLAN_VENDOR_RSI \ + WLAN_VENDOR_ST \ + WLAN_VENDOR_TI \ + WLAN_VENDOR_ZYDAS \ + +config-$(call config_package,cfg80211,$(ALL_VARIANTS)) += CFG80211 +config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE + +config-$(call config_package,mac80211,$(ALL_VARIANTS)) += MAC80211 +config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH + +include ath.mk +include broadcom.mk +include intel.mk +include marvell.mk +include ralink.mk +include realtek.mk + +PKG_CONFIG_DEPENDS += \ + CONFIG_WIFI_SCRIPTS_UCODE \ + $(patsubst %,CONFIG_PACKAGE_kmod-%,$(PKG_DRIVERS)) + +define KernelPackage/cfg80211 + $(call KernelPackage/mac80211/Default) + TITLE:=cfg80211 - wireless configuration API + DEPENDS+= +iw +!WIFI_SCRIPTS_UCODE:iwinfo +wifi-scripts +wireless-regdb +USE_RFKILL:kmod-rfkill + ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) + FILES:= \ + $(PKG_BUILD_DIR)/compat/compat.ko \ + $(PKG_BUILD_DIR)/net/wireless/cfg80211.ko +endef + +define KernelPackage/cfg80211/description +cfg80211 is the Linux wireless LAN (802.11) configuration API. +endef + +define KernelPackage/cfg80211/config + if PACKAGE_kmod-cfg80211 + + config PACKAGE_CFG80211_TESTMODE + bool "Enable testmode command support" + default n + help + This is typically used for tests and calibration during + manufacturing, or vendor specific debugging features + + endif +endef + + +define KernelPackage/mac80211 + $(call KernelPackage/mac80211/Default) + TITLE:=Linux 802.11 Wireless Networking Stack + # +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c + DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common + KCONFIG:=\ + CONFIG_AVERAGE=y + FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko + ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) + MENU:=1 +endef + +define KernelPackage/mac80211/config + if PACKAGE_kmod-mac80211 + + config PACKAGE_MAC80211_DEBUGFS + bool "Export mac80211 internals in DebugFS" + select KERNEL_DEBUG_FS + default y + help + Select this to see extensive information about + the internal state of mac80211 in debugfs. + + config PACKAGE_MAC80211_TRACING + bool "Enable tracing (mac80211 and supported drivers)" + select KERNEL_FTRACE + select KERNEL_ENABLE_DEFAULT_TRACERS + default n + help + Select this to enable tracing of mac80211 and + related wifi drivers (using trace-cmd). + + config PACKAGE_MAC80211_MESH + bool "Enable 802.11s mesh support" + default y + + endif +endef + +define KernelPackage/mac80211/description +Generic IEEE 802.11 Networking Stack (mac80211) +endef + +define KernelPackage/mac80211-hwsim + $(call KernelPackage/mac80211/Default) + TITLE:=mac80211 HW simulation device + DEPENDS+= +kmod-mac80211 +@DRIVER_11BE_SUPPORT +@DRIVER_11AX_SUPPORT +@DRIVER_11AC_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/virtual/mac80211_hwsim.ko + AUTOLOAD:=$(call AutoProbe,mac80211_hwsim) +endef + + +define KernelPackage/mt7601u + $(call KernelPackage/mac80211/Default) + TITLE:=MT7601U-based USB dongles Wireless Driver + DEPENDS+= +kmod-mac80211 @USB_SUPPORT +kmod-usb-core +mt7601u-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko + AUTOLOAD:=$(call AutoProbe,mt7601u) +endef + +define KernelPackage/rsi91x + $(call KernelPackage/mac80211/Default) + TITLE:=Redpine Signals Inc 91x WLAN driver support + DEPENDS+= +kmod-mac80211 +rs9113-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_91x.ko +endef + +define KernelPackage/rsi91x-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Redpine Signals USB bus support + DEPENDS+=@USB_SUPPORT +kmod-usb-core +kmod-mac80211 +kmod-rsi91x +rs9113-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_usb.ko + AUTOLOAD:=$(call AutoProbe,rsi_usb) +endef + +define KernelPackage/rsi91x-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Redpine Signals SDIO bus support + DEPENDS+= +kmod-mac80211 +kmod-mmc +kmod-rsi91x +rs9113-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_sdio.ko + AUTOLOAD:=$(call AutoProbe,rsi_sdio) +endef + + +define KernelPackage/wlcore + $(call KernelPackage/mac80211/Default) + TITLE:=TI common driver part + DEPENDS+= +kmod-mmc +kmod-mac80211 + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko + AUTOLOAD:=$(call AutoProbe,wlcore wlcore_sdio) +endef + +define KernelPackage/wlcore/description + This module contains some common parts needed by TI Wireless drivers. +endef + +define KernelPackage/wl12xx + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for TI WL12xx + URL:=https://wireless.wiki.kernel.org/en/users/drivers/wl12xx + DEPENDS+= +kmod-wlcore +wl12xx-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko + AUTOLOAD:=$(call AutoProbe,wl12xx) +endef + +define KernelPackage/wl12xx/description + Kernel modules for TI WL12xx +endef + +define KernelPackage/wl18xx + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for TI WL18xx + URL:=https://wireless.wiki.kernel.org/en/users/drivers/wl18xx + DEPENDS+= +kmod-wlcore +wl18xx-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl18xx/wl18xx.ko + AUTOLOAD:=$(call AutoProbe,wl18xx) +endef + +define KernelPackage/wl18xx/description + Kernel modules for TI WL18xx +endef + + +ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS + config-y += \ + CFG80211_DEBUGFS \ + MAC80211_DEBUGFS +endif + +ifdef CONFIG_PACKAGE_MAC80211_TRACING + config-y += \ + IWLWIFI_DEVICE_TRACING +endif + +config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM +config-$(call config_package,mt7601u) += MT7601U +config-y += WL_MEDIATEK + +config-$(call config_package,wlcore) += WLCORE WLCORE_SDIO +config-$(call config_package,wl12xx) += WL12XX +config-$(call config_package,wl18xx) += WL18XX +config-y += WL_TI WILINK_PLATFORM_DATA +config-$(call config_package,rsi91x) += RSI_91X +config-$(call config_package,rsi91x-usb) += RSI_USB +config-$(call config_package,rsi91x-sdio) += RSI_SDIO + +config-$(CONFIG_LEDS_TRIGGERS) += MAC80211_LEDS + +C_DEFINES= + +ifeq ($(BUILD_VARIANT),smallbuffers) + C_DEFINES+= -DCONFIG_ATH10K_SMALLBUFFERS +endif + +MAKE_OPTS:= \ + $(subst -C $(LINUX_DIR),-C "$(PKG_BUILD_DIR)",$(KERNEL_MAKEOPTS)) \ + EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES)" \ + KLIB_BUILD="$(LINUX_DIR)" \ + MODPROBE=true \ + KLIB=$(TARGET_MODULES_DIR) \ + KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER))) \ + KBUILD_LDFLAGS_MODULE_PREREQ= + +define ConfigVars +$(subst $(space),,$(foreach opt,$(config-$(1)),CPTCFG_$(opt)=$(1) +)) +endef + +define mac80211_config +$(call ConfigVars,m)$(call ConfigVars,y) +endef +$(eval $(call shexport,mac80211_config)) + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + $(PKG_UNPACK) + $(Build/Patch) + rm -rf \ + $(PKG_BUILD_DIR)/include/linux/ssb \ + $(PKG_BUILD_DIR)/include/linux/bcma \ + $(PKG_BUILD_DIR)/include/net/bluetooth + + rm -f \ + $(PKG_BUILD_DIR)/include/linux/cordic.h \ + $(PKG_BUILD_DIR)/include/linux/crc8.h \ + $(PKG_BUILD_DIR)/include/linux/eeprom_93cx6.h \ + $(PKG_BUILD_DIR)/include/linux/wl12xx.h \ + $(PKG_BUILD_DIR)/include/linux/mhi.h \ + $(PKG_BUILD_DIR)/include/net/ieee80211.h \ + $(PKG_BUILD_DIR)/backport-include/linux/bcm47xx_nvram.h + + echo 'compat-wireless-$(PKG_VERSION)-$(PKG_RELEASE)-$(REVISION)' > $(PKG_BUILD_DIR)/compat_version +endef + +ifneq ($(CONFIG_PACKAGE_kmod-cfg80211),) + define Build/Compile/kmod + rm -rf $(PKG_BUILD_DIR)/modules + +$(MAKE) $(PKG_JOBS) $(MAKE_OPTS) modules + endef +endif + +#do not Build/Configure for EXTERNAL KERNEL +ifeq ($(strip $(CONFIG_EXTERNAL_KERNEL_TREE)),"") + ifeq ($(strip $(CONFIG_KERNEL_GIT_CLONE_URI)),"") + define Build/Configure + cmp $(PKG_BUILD_DIR)/include/linux/ath5k_platform.h $(LINUX_DIR)/include/linux/ath5k_platform.h + endef + endif +endif + +define Build/Patch + $(if $(QUILT),rm -rf $(PKG_BUILD_DIR)/patches; mkdir -p $(PKG_BUILD_DIR)/patches) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath5k,ath5k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath9k,ath9k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath10k,ath10k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath11k,ath11k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath12k,ath12k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mt7601u,mt7601u/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rtl,rtl/) + $(if $(QUILT),touch $(PKG_BUILD_DIR)/.quilt_used) +endef + +define Quilt/Refresh/Package + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath5k,ath5k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath9k,ath9k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath10k,ath10k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath11k,ath11k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath12k,ath12k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mt7601u,mt7601u/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rtl,rtl/) +endef + +define Build/Compile + $(SH_FUNC) var2file "$(call shvar,mac80211_config)" $(PKG_BUILD_DIR)/.config + $(MAKE) $(MAKE_OPTS) allnoconfig + $(call Build/Compile/kmod) +endef + +define Build/InstallDev + mkdir -p \ + $(1)/usr/include/mac80211 \ + $(1)/usr/include/mac80211-backport \ + $(1)/usr/include/mac80211/ath \ + $(1)/usr/include/net/mac80211 + $(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/ + $(CP) $(PKG_BUILD_DIR)/backport-include/* $(1)/usr/include/mac80211-backport/ + $(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/ + $(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/ + rm -f $(1)/usr/include/mac80211-backport/linux/module.h +endef + + +$(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv)))) +$(eval $(call KernelPackage,cfg80211)) +$(eval $(call KernelPackage,mac80211)) diff --git a/ath.mk b/ath.mk new file mode 100644 index 0000000..593eca6 --- /dev/null +++ b/ath.mk @@ -0,0 +1,435 @@ +PKG_DRIVERS += \ + ath ath5k ath6kl ath6kl-sdio ath6kl-usb ath9k ath9k-common ath9k-htc ath10k ath10k-sdio ath10k-smallbuffers \ + ath11k ath11k-ahb ath11k-pci ath12k carl9170 owl-loader ar5523 wil6210 qcom-qmi-helpers + +PKG_CONFIG_DEPENDS += \ + CONFIG_PACKAGE_ATH_DEBUG \ + CONFIG_PACKAGE_ATH_DFS \ + CONFIG_PACKAGE_ATH_SPECTRAL \ + CONFIG_PACKAGE_ATH_DYNACK \ + CONFIG_ATH9K_HWRNG \ + CONFIG_ATH9K_SUPPORT_PCOEM \ + CONFIG_ATH9K_TX99 \ + CONFIG_ATH10K_LEDS \ + CONFIG_ATH10K_THERMAL \ + CONFIG_ATH11K_THERMAL \ + CONFIG_ATH_USER_REGD + +ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS + config-y += \ + ATH9K_DEBUGFS \ + ATH9K_HTC_DEBUGFS \ + ATH10K_DEBUGFS \ + ATH11K_DEBUGFS \ + ATH12K_DEBUGFS \ + CARL9170_DEBUGFS \ + ATH5K_DEBUG \ + ATH6KL_DEBUG \ + WIL6210_DEBUGFS +endif + +ifdef CONFIG_PACKAGE_MAC80211_TRACING + config-y += \ + ATH10K_TRACING \ + ATH11K_TRACING \ + ATH12K_TRACING \ + ATH6KL_TRACING \ + ATH_TRACEPOINTS \ + ATH5K_TRACER \ + WIL6210_TRACING +endif + +config-$(call config_package,qcom-qmi-helpers) += QCOM_QMI_HELPERS +config-$(call config_package,ath,regular sdio smallbuffers) += ATH_CARDS ATH_COMMON +config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG ATH11K_DEBUG ATH12K_DEBUG ATH9K_STATION_STATISTICS +config-$(CONFIG_PACKAGE_ATH_DFS) += ATH9K_DFS_CERTIFIED ATH10K_DFS_CERTIFIED +config-$(CONFIG_PACKAGE_ATH_SPECTRAL) += ATH9K_COMMON_SPECTRAL ATH10K_SPECTRAL ATH11K_SPECTRAL +config-$(CONFIG_PACKAGE_ATH_DYNACK) += ATH9K_DYNACK +config-$(call config_package,ath9k) += ATH9K +config-$(call config_package,ath9k-common) += ATH9K_COMMON +config-$(call config_package,owl-loader) += ATH9K_PCI_NO_EEPROM +config-$(CONFIG_TARGET_ath79) += ATH9K_AHB +config-$(CONFIG_TARGET_ipq40xx) += ATH10K_AHB +config-$(CONFIG_PCI) += ATH9K_PCI +config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD ATH_REG_DYNAMIC_USER_REG_HINTS +config-$(CONFIG_ATH9K_HWRNG) += ATH9K_HWRNG +config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM +config-$(CONFIG_ATH9K_TX99) += ATH9K_TX99 +config-$(CONFIG_ATH9K_UBNTHSR) += ATH9K_UBNTHSR +config-$(CONFIG_ATH10K_LEDS) += ATH10K_LEDS +config-$(CONFIG_ATH10K_THERMAL) += ATH10K_THERMAL +config-$(CONFIG_ATH11K_THERMAL) += ATH11K_THERMAL + +config-$(call config_package,ath9k-htc) += ATH9K_HTC +config-$(call config_package,ath10k,regular) += ATH10K ATH10K_PCI +config-$(call config_package,ath10k-sdio,sdio) += ATH10K ATH10K_SDIO +config-$(call config_package,ath10k-smallbuffers,smallbuffers) += ATH10K ATH10K_PCI ATH10K_SMALLBUFFERS +config-$(call config_package,ath11k) += ATH11K +config-$(call config_package,ath11k-ahb) += ATH11K_AHB +config-$(call config_package,ath11k-pci) += ATH11K_PCI +config-$(call config_package,ath12k) += ATH12K + +config-$(call config_package,ath5k) += ATH5K ATH5K_PCI + +config-$(call config_package,ath6kl) += ATH6KL +config-$(call config_package,ath6kl-sdio) += ATH6KL_SDIO +config-$(call config_package,ath6kl-usb) += ATH6KL_USB + +config-$(call config_package,carl9170) += CARL9170 +config-$(call config_package,ar5523) += AR5523 + +config-$(call config_package,wil6210) += WIL6210 + +define KernelPackage/ath/config + if PACKAGE_kmod-ath + config ATH_USER_REGD + bool "Force Atheros drivers to respect the user's regdomain settings" + default y + help + Atheros' idea of regulatory handling is that the EEPROM of the card defines + the regulatory limits and the user is only allowed to restrict the settings + even further, even if the country allows frequencies or power levels that + are forbidden by the EEPROM settings. + + Select this option if you want the driver to respect the user's decision about + regulatory settings. + + config PACKAGE_ATH_DEBUG + bool "Atheros wireless debugging" + help + Say Y, if you want to debug atheros wireless drivers. + Only ath9k & ath10k & ath11k make use of this. + + config PACKAGE_ATH_DFS + bool "Enable DFS support" + default y + help + Dynamic frequency selection (DFS) is required for most of the 5 GHz band + channels in Europe, US, and Japan. + + Select this option if you want to use such channels. + + config PACKAGE_ATH_SPECTRAL + bool "Atheros spectral scan support" + depends on PACKAGE_ATH_DEBUG + select KERNEL_RELAY + help + Say Y to enable access to the FFT/spectral data via debugfs. + + config PACKAGE_ATH_DYNACK + bool "Enable Dynack support" + depends on PACKAGE_kmod-ath9k-common + help + Enables support for Dynamic ACK estimation, which allows the fastest possible speed + at any distance automatically by increasing/decreasing the max frame ACK time for + the most remote station detected. It can be enabled by using iw (iw phy0 set distance auto), + or by sending the NL80211_ATTR_WIPHY_DYN_ACK flag to mac80211 driver using netlink. + + Select this option if you want to enable this feature + + endif +endef + +define KernelPackage/qcom-qmi-helpers + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm QMI backports helpers + HIDDEN:=1 + FILES:=$(PKG_BUILD_DIR)/drivers/soc/qcom/qmi_helpers.ko + AUTOLOAD:=$(call AutoProbe,qmi_helpers) +endef + +define KernelPackage/ath + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros common driver part + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79 +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko + MENU:=1 +endef + +define KernelPackage/ath/description + This module contains some common parts needed by Atheros Wireless drivers. +endef + +define KernelPackage/ath5k + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 5xxx wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath5k + DEPENDS+= @PCI_SUPPORT +kmod-ath + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko + AUTOLOAD:=$(call AutoProbe,ath5k) +endef + +define KernelPackage/ath5k/description + This module adds support for wireless adapters based on + Atheros 5xxx chipset. +endef + +define KernelPackage/ath6kl + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros FullMAC wireless devices (common code for ath6kl_sdio and ath6kl_usb) + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath6kl + HIDDEN:=1 + DEPENDS+= +kmod-ath + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_core.ko +endef + +define KernelPackage/ath6kl-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n SDIO wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath6kl + DEPENDS+= +kmod-mmc +kmod-ath6kl + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_sdio.ko + AUTOLOAD:=$(call AutoProbe,ath6kl_sdio) +endef + +define KernelPackage/ath6kl-sdio/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11n AR6003 and AR6004 family of chipsets. +endef + +define KernelPackage/ath6kl-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n USB wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath6kl + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-ath6kl + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_usb.ko + AUTOLOAD:=$(call AutoProbe,ath6kl_usb) +endef + +define KernelPackage/ath6kl-usb/description +This module adds support for wireless adapters based on the +Atheros IEEE 802.11n AR6004 chipset. +endef + +define KernelPackage/ath9k-common + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc) + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k + HIDDEN:=1 + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79 +kmod-ath +kmod-random-core + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko +endef + +define KernelPackage/ath9k + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n PCI wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k + DEPENDS+= @PCI_SUPPORT||TARGET_ath79 +kmod-ath9k-common + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko + AUTOLOAD:=$(call AutoProbe,ath9k) +endef + +define KernelPackage/ath9k/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. +endef + +define KernelPackage/ath9k/config + + config ATH9K_HWRNG + bool "Add wireless noise as source of randomness to kernel entropy pool" + depends on PACKAGE_kmod-ath9k + select PACKAGE_kmod-random-core + default y + + config ATH9K_SUPPORT_PCOEM + bool "Support chips used in PC OEM cards" + depends on PACKAGE_kmod-ath9k + default y if (x86_64 || i386) + + config ATH9K_TX99 + bool "Enable TX99 support (WARNING: testing only, breaks normal operation!)" + depends on PACKAGE_kmod-ath9k + + config ATH9K_UBNTHSR + bool "Support for Ubiquiti UniFi Outdoor+ access point" + depends on PACKAGE_kmod-ath9k && TARGET_ath79 + default y + +endef + +define KernelPackage/ath9k-htc + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n USB device support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k + DEPENDS+= @USB_SUPPORT +kmod-ath9k-common +kmod-usb-core +ath9k-htc-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_htc.ko + AUTOLOAD:=$(call AutoProbe,ath9k_htc) +endef + +define KernelPackage/ath9k-htc/description +This module adds support for wireless adapters based on +Atheros USB AR9271 and AR7010 family of chipsets. +endef + +define KernelPackage/ath10k + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11ac wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath10k + DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11AC_SUPPORT \ + +ATH10K_THERMAL:kmod-hwmon-core +ATH10K_THERMAL:kmod-thermal + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko + AUTOLOAD:=$(call AutoProbe,ath10k_core ath10k_pci) + MODPARAMS.ath10k_core:=frame_mode=2 + VARIANT:=regular +endef + +define KernelPackage/ath10k/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11ac family of chipsets. For now only +PCI is supported. +endef + +define KernelPackage/ath10k/config + + config ATH10K_LEDS + bool "Enable LED support" + default y + depends on PACKAGE_kmod-ath10k || PACKAGE_kmod-ath10k-smallbuffers + + config ATH10K_THERMAL + bool "Enable thermal sensors and throttling support" + default y + depends on PACKAGE_kmod-ath10k || PACKAGE_kmod-ath10k-sdio || PACKAGE_kmod-ath10k-smallbuffers + +endef + +define KernelPackage/ath10k-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11ac SDIO wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath10k + DEPENDS+= +kmod-ath +kmod-mmc +@DRIVER_11AC_SUPPORT \ + +ATH10K_THERMAL:kmod-hwmon-core +ATH10K_THERMAL:kmod-thermal + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_sdio.ko + AUTOLOAD:=$(call AutoProbe,ath10k_core) + MODPARAMS.ath10k_core:=frame_mode=2 + VARIANT:=sdio +endef + +define KernelPackage/ath10k-sdio/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11ac family of chipsets with SDIO bus. +endef + +define KernelPackage/ath10k-smallbuffers + $(call KernelPackage/ath10k) + TITLE+= (small buffers for low-RAM devices) + VARIANT:=smallbuffers +endef + +define KernelPackage/ath11k + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm 802.11ax wireless chipset support (common code) + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k + DEPENDS+= +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \ + +kmod-crypto-michael-mic +ATH11K_THERMAL:kmod-hwmon-core \ + +ATH11K_THERMAL:kmod-thermal +kmod-qcom-qmi-helpers + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k.ko +endef + +define KernelPackage/ath11k/description +This module adds support for Qualcomm Technologies 802.11ax family of +chipsets. +endef + +define KernelPackage/ath11k/config + + config ATH11K_THERMAL + bool "Enable thermal sensors and throttling support" + depends on PACKAGE_kmod-ath11k + default y if TARGET_qualcommax + +endef + +define KernelPackage/ath11k-ahb + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm 802.11ax AHB wireless chipset support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k + DEPENDS+= @TARGET_qualcommax +kmod-ath11k +kmod-qrtr-smd + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k_ahb.ko + AUTOLOAD:=$(call AutoProbe,ath11k_ahb) +endef + +define KernelPackage/ath11k-ahb/description +This module adds support for Qualcomm Technologies 802.11ax family of +chipsets with AHB bus. +endef + +define KernelPackage/ath11k-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm 802.11ax PCI wireless chipset support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k + DEPENDS+= @PCI_SUPPORT +kmod-qrtr-mhi +kmod-ath11k + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k_pci.ko + AUTOLOAD:=$(call AutoProbe,ath11k_pci) +endef + +define KernelPackage/ath11k-pci/description +This module adds support for Qualcomm Technologies 802.11ax family of +chipsets with PCI bus. +endef + +define KernelPackage/ath12k + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm 802.11be wireless chipset support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath12k + DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \ + +kmod-crypto-michael-mic +kmod-qrtr-mhi \ + +kmod-qcom-qmi-helpers +@DRIVER_11BE_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath12k/ath12k.ko + AUTOLOAD:=$(call AutoProbe,ath12k) +endef + +define KernelPackage/ath12k/description +This module adds support for Qualcomm Technologies 802.11be family of +chipsets with PCI bus. +endef + +define KernelPackage/carl9170 + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Atheros AR9170 USB sticks + DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +carl9170-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko + AUTOLOAD:=$(call AutoProbe,carl9170) +endef + +define KernelPackage/owl-loader + $(call KernelPackage/mac80211/Default) + TITLE:=Owl loader for initializing Atheros PCI(e) Wifi chips + DEPENDS:=@PCI_SUPPORT +kmod-ath9k + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.ko + AUTOLOAD:=$(call AutoProbe,ath9k_pci_owl_loader) +endef + +define KernelPackage/owl-loader/description + Kernel module that helps to initialize certain Qualcomm + Atheros' PCI(e) Wifi chips, which have the init data + (which contains the PCI device ID for example) stored + together with the calibration data in the file system. + + This is necessary for devices like the Cisco Meraki Z1. +endef + +define KernelPackage/ar5523 + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Atheros AR5523 USB sticks + DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ar5523/ar5523.ko + AUTOLOAD:=$(call AutoProbe,ar5523) +endef + +define KernelPackage/wil6210 + $(call KernelPackage/mac80211/Default) + TITLE:=QCA/Wilocity 60g WiFi card wil6210 support + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +wil6210-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/wil6210/wil6210.ko + AUTOLOAD:=$(call AutoProbe,wil6210) +endef diff --git a/broadcom.mk b/broadcom.mk new file mode 100644 index 0000000..444d705 --- /dev/null +++ b/broadcom.mk @@ -0,0 +1,497 @@ +PKG_DRIVERS += \ + b43 brcmsmac brcmfmac brcmutil + +PKG_CONFIG_DEPENDS += \ + CONFIG_PACKAGE_B43_DEBUG \ + CONFIG_PACKAGE_B43_PIO \ + CONFIG_PACKAGE_B43_PHY_G \ + CONFIG_PACKAGE_B43_PHY_N \ + CONFIG_PACKAGE_B43_PHY_LP \ + CONFIG_PACKAGE_B43_PHY_HT \ + CONFIG_PACKAGE_B43_BUSES_BCMA_AND_SSB \ + CONFIG_PACKAGE_B43_BUSES_BCMA \ + CONFIG_PACKAGE_B43_BUSES_SSB \ + CONFIG_PACKAGE_BRCM80211_DEBUG + +config-$(call config_package,b43) += B43 +config-$(CONFIG_PACKAGE_B43_BUSES_BCMA_AND_SSB) += B43_BUSES_BCMA_AND_SSB +config-$(CONFIG_PACKAGE_B43_BUSES_BCMA) += B43_BUSES_BCMA +config-$(CONFIG_PACKAGE_B43_BUSES_SSB) += B43_BUSES_SSB +config-$(CONFIG_PACKAGE_B43_PHY_G) += B43_PHY_G +config-$(CONFIG_PACKAGE_B43_PHY_N) += B43_PHY_N +config-$(CONFIG_PACKAGE_B43_PHY_LP) += B43_PHY_LP +config-$(CONFIG_PACKAGE_B43_PHY_HT) += B43_PHY_HT +config-$(CONFIG_PACKAGE_B43_PIO) += B43_PIO +config-$(CONFIG_PACKAGE_B43_DEBUG) += B43_DEBUG + +config-$(call config_package,brcmutil) += BRCMUTIL +config-$(call config_package,brcmsmac) += BRCMSMAC +config-$(call config_package,brcmfmac) += BRCMFMAC +config-$(CONFIG_BRCMFMAC_SDIO) += BRCMFMAC_SDIO +config-$(CONFIG_BRCMFMAC_USB) += BRCMFMAC_USB +config-$(CONFIG_BRCMFMAC_PCIE) += BRCMFMAC_PCIE +config-$(CONFIG_PACKAGE_BRCM80211_DEBUG) += BRCMDBG + +config-$(CONFIG_LEDS_TRIGGERS) += B43_LEDS B43LEGACY_LEDS + +#Broadcom firmware +ifneq ($(CONFIG_B43_FW_6_30),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=6.30.163.46 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).wl_apsta.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/ + PKG_B43_FWV4_HASH:=a07c3b6b277833c7dbe61daa511f908cd66c5e2763eb7a0859abc36cd9335c2d +else +ifneq ($(CONFIG_B43_FW_5_10),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=5.10.56.27.3 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta/wl_prebuilt.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)_mipsel.tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=@OPENWRT + PKG_B43_FWV4_HASH:=26a8c370f48fc129d0731cfd751c36cae1419b0bc8ca35781126744e60eae009 +else +ifneq ($(CONFIG_B43_FW_4_178),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=4.178.10.4 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=@OPENWRT + PKG_B43_FWV4_HASH:=32f6ad98facbb9045646fdc8b54bb03086d204153253f9c65d0234a5d90ae53f +else +ifneq ($(CONFIG_B43_FW_5_100_138),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=5.100.138 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/ + PKG_B43_FWV4_HASH:=f1e7067aac5b62b67b8b6e4c517990277804339ac16065eb13c731ff909ae46f +else + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=4.150.10.5 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta_mimo.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=@OPENWRT + PKG_B43_FWV4_HASH:=a9f4e276a4d8d3a1cd0f2eb87080ae89b77f0a7140f06d4e9e2135fc44fdd533 +endif +endif +endif +endif +ifneq ($(CONFIG_B43_OPENFIRMWARE),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=5.2 + PKG_B43_FWV4_OBJECT:=openfwwf-$(PKG_B43_FWV4_VERSION) + PKG_B43_FWV4_SOURCE:=openfwwf-$(PKG_B43_FWV4_VERSION).tar.gz + PKG_B43_FWV4_SOURCE_URL:=http://netweb.ing.unibs.it/~openfwwf/firmware + PKG_B43_FWV4_HASH:=9de03320083201080b2e94b81637ac07a159cf4e6f3481383e1a217e627bc0dc +endif + + +define Download/b43 + FILE:=$(PKG_B43_FWV4_SOURCE) + URL:=$(PKG_B43_FWV4_SOURCE_URL) + HASH:=$(PKG_B43_FWV4_HASH) +endef +$(eval $(call Download,b43)) + +define KernelPackage/b43 + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom 43xx wireless support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43 + KCONFIG:= \ + CONFIG_HW_RANDOM=y + # Depend on PCI_SUPPORT to make sure we can select kmod-bcma or kmod-ssb + DEPENDS += \ + @PCI_SUPPORT +kmod-mac80211 +kmod-lib-cordic \ + $(if $(CONFIG_PACKAGE_B43_USE_SSB),+kmod-ssb) \ + $(if $(CONFIG_PACKAGE_B43_USE_BCMA),+kmod-bcma) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/b43/b43.ko + AUTOLOAD:=$(call AutoProbe,b43) + MENU:=1 +endef + +define KernelPackage/b43/config + +config PACKAGE_B43_USE_SSB + select PACKAGE_kmod-ssb + tristate + depends on !TARGET_bcm47xx && !TARGET_bcm63xx + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_SSB + +config PACKAGE_B43_USE_BCMA + select PACKAGE_kmod-bcma + tristate + depends on !TARGET_bcm47xx && !TARGET_bcm53xx + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA + + if PACKAGE_kmod-b43 + + choice + prompt "b43 firmware version" + default B43_FW_5_100_138 + help + This option allows you to select the version of the b43 firmware. + + config B43_FW_4_150 + bool "Firmware 410.2160 from driver 4.150.10.5 (old stable)" + help + Old stable firmware for BCM43xx devices. + + If unsure, select this. + + config B43_FW_4_178 + bool "Firmware 478.104 from driver 4.178.10.4" + help + Older firmware for BCM43xx devices. + + If unsure, select the "stable" firmware. + + config B43_FW_5_10 + bool "Firmware 508.1084 from driver 5.10.56.27" + help + Older firmware for BCM43xx devices. + + If unsure, select the "stable" firmware. + + config B43_FW_5_100_138 + bool "Firmware 666.2 from driver 5.100.138 (stable)" + help + The currently default firmware for BCM43xx devices. + + This firmware currently gets most of the testing and is needed for some N-PHY devices. + + If unsure, select the this firmware. + + config B43_FW_6_30 + bool "Firmware 784.2 from driver 6.30.163.46 (experimental)" + help + Newer experimental firmware for BCM43xx devices. + + This firmware is mostly untested. + + If unsure, select the "stable" firmware. + + config B43_OPENFIRMWARE + bool "Open FirmWare for WiFi networks" + help + Opensource firmware for BCM43xx devices. + + Do _not_ select this, unless you know what you are doing. + The Opensource firmware is not suitable for embedded devices, yet. + It does not support QoS, which is bad for AccessPoints. + It does not support hardware crypto acceleration, which is a showstopper + for embedded devices with low CPU resources. + + If unsure, select the "stable" firmware. + + endchoice + + config B43_FW_SQUASH + bool "Remove unnecessary firmware files" + depends on !B43_OPENFIRMWARE + default y + help + This options allows you to remove unnecessary b43 firmware files + from the final rootfs image. This can reduce the rootfs size by + up to 200k. + + If unsure, say Y. + + config B43_FW_SQUASH_COREREVS + string "Core revisions to include" + depends on B43_FW_SQUASH + default "5,6,7,8,9,10,11,13,15" if TARGET_bcm47xx_legacy + default "16,28,29,30" if TARGET_bcm47xx_mips74k + default "5,6,7,8,9,10,11,13,15,16,28,29,30" + help + This is a comma separated list of core revision numbers. + + Example (keep files for rev5 only): + 5 + + Example (keep files for rev5 and rev11): + 5,11 + + config B43_FW_SQUASH_PHYTYPES + string "PHY types to include" + depends on B43_FW_SQUASH + default "G,N,LP" if TARGET_bcm47xx_legacy + default "N,HT" if TARGET_bcm47xx_mips74k + default "G,N,LP,HT" + help + This is a comma separated list of PHY types: + A => A-PHY + AG => Dual A-PHY G-PHY + G => G-PHY + LP => LP-PHY + N => N-PHY + HT => HT-PHY + LCN => LCN-PHY + LCN40 => LCN40-PHY + AC => AC-PHY + + Example (keep files for G-PHY only): + G + + Example (keep files for G-PHY and N-PHY): + G,N + + choice + prompt "Supported buses" + default PACKAGE_B43_BUSES_BCMA_AND_SSB + help + This allows choosing buses that b43 should support. + + config PACKAGE_B43_BUSES_BCMA_AND_SSB + depends on !TARGET_bcm47xx_legacy && !TARGET_bcm47xx_mips74k && !TARGET_bcm53xx && !TARGET_bmips + bool "BCMA and SSB" + + config PACKAGE_B43_BUSES_BCMA + depends on !TARGET_bcm47xx_legacy && !TARGET_bmips_bcm6358 && !TARGET_bmips_bcm6368 + bool "BCMA only" + + config PACKAGE_B43_BUSES_SSB + depends on !TARGET_bcm47xx_mips74k && !TARGET_bcm53xx + bool "SSB only" + + endchoice + + config PACKAGE_B43_DEBUG + bool "Enable debug output and debugfs for b43" + default n + help + Enable additional debug output and runtime sanity checks for b43 + and enables the debugfs interface. + + If unsure, say N. + + config PACKAGE_B43_PIO + bool "Enable support for PIO transfer mode" + default n + help + Enable support for using PIO instead of DMA. Unless you have DMA + transfer problems you don't need this. + + If unsure, say N. + + config PACKAGE_B43_PHY_G + bool "Enable support for G-PHYs" + default n if TARGET_bcm47xx_mips74k + default y + help + Enable support for G-PHY. This includes support for the following devices: + PCI: BCM4306, BCM4311, BCM4318 + SoC: BCM5352E, BCM4712 + + If unsure, say Y. + + config PACKAGE_B43_PHY_N + bool "Enable support for N-PHYs" + default y + help + Enable support for N-PHY. This includes support for the following devices: + PCI: BCM4321, BCM4322, BCM43222, BCM43224, BCM43225 + SoC: BCM4716, BCM4717, BCM4718 + + Currently only 11g speed is available. + + If unsure, say Y. + + config PACKAGE_B43_PHY_LP + bool "Enable support for LP-PHYs" + default n if TARGET_bcm47xx_mips74k + default y + help + Enable support for LP-PHY. This includes support for the following devices: + PCI: BCM4312 + SoC: BCM5354 + + If unsure, say Y. + + config PACKAGE_B43_PHY_HT + bool "Enable support for HT-PHYs" + default n if TARGET_bcm47xx_legacy + default y + help + Enable support for HT-PHY. This includes support for the following devices: + PCI: BCM4331 + + Currently only 11g speed is available. + + If unsure, say Y. + + config PACKAGE_B43_PHY_LCN + bool "Enable support for LCN-PHYs" + depends on BROKEN + default n + help + Currently broken. + + If unsure, say N. + + endif +endef + +define KernelPackage/b43/description +Kernel module for Broadcom 43xx wireless support (mac80211 stack) new +endef + +define KernelPackage/brcmutil + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom IEEE802.11n common driver parts + URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 + DEPENDS+=@PCI_SUPPORT||USB_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmutil/brcmutil.ko + AUTOLOAD:=$(call AutoProbe,brcmutil) + MENU:=1 +endef + +define KernelPackage/brcmutil/description + This module contains some common parts needed by Broadcom Wireless drivers brcmsmac and brcmfmac. +endef + +define KernelPackage/brcmutil/config + if PACKAGE_kmod-brcmutil + + config PACKAGE_BRCM80211_DEBUG + bool "Broadcom wireless driver debugging" + help + Say Y, if you want to debug brcmsmac and brcmfmac wireless driver. + + endif +endef + +PKG_BRCMSMAC_FW_NAME:=broadcom-wl +PKG_BRCMSMAC_FW_VERSION:=5.100.138 +PKG_BRCMSMAC_FW_OBJECT:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION)/linux/wl_apsta.o +PKG_BRCMSMAC_FW_SOURCE:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION).tar.bz2 +PKG_BRCMSMAC_FW_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/ +PKG_BRCMSMAC_FW_HASH:=f1e7067aac5b62b67b8b6e4c517990277804339ac16065eb13c731ff909ae46f + +define Download/brcmsmac + FILE:=$(PKG_BRCMSMAC_FW_SOURCE) + URL:=$(PKG_BRCMSMAC_FW_SOURCE_URL) + HASH:=$(PKG_BRCMSMAC_FW_HASH) +endef +$(eval $(call Download,brcmsmac)) + +define KernelPackage/brcmsmac + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom IEEE802.11n PCIe SoftMAC WLAN driver + URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 + DEPENDS+=@!TARGET_bcm47xx_legacy +kmod-mac80211 +!TARGET_bcm47xx:kmod-bcma +kmod-lib-cordic +kmod-lib-crc8 +kmod-brcmutil +!BRCMSMAC_USE_FW_FROM_WL:brcmsmac-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcmsmac.ko + AUTOLOAD:=$(call AutoProbe,brcmsmac) + MENU:=1 +endef + +define KernelPackage/brcmsmac/description + Kernel module for Broadcom IEEE802.11n PCIe Wireless cards +endef + +define KernelPackage/brcmsmac/config + if PACKAGE_kmod-brcmsmac + + config BRCMSMAC_USE_FW_FROM_WL + bool "Use firmware extracted from broadcom proprietary driver" + default y + help + Instead of using the official brcmsmac firmware a firmware + version 666.2 extracted from the proprietary Broadcom driver + is used. This is needed to get core rev 17 used in bcm4716 + to work. + + If unsure, say Y. + + endif +endef + + +define KernelPackage/brcmfmac + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver + URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 + DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11AC_SUPPORT \ + +kmod-brcmutil +BRCMFMAC_SDIO:kmod-mmc @!TARGET_uml \ + +BRCMFMAC_USB:kmod-usb-core +BRCMFMAC_USB:brcmfmac-firmware-usb + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko \ + $(foreach type,bca cyw wcc, \ + $(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmfmac/$(type)/brcmfmac-$(type).ko) + AUTOLOAD:=$(call AutoProbe,brcmfmac) +endef + +define KernelPackage/brcmfmac/description + Kernel module for Broadcom IEEE802.11n USB Wireless cards +endef + +define KernelPackage/brcmfmac/config + if PACKAGE_kmod-brcmfmac + + config BRCMFMAC_SDIO + bool "Enable SDIO bus interface support" + default y if TARGET_bcm27xx + default y if TARGET_imx_cortexa7 + default y if TARGET_starfive + default y if TARGET_rockchip + default y if TARGET_sunxi + default y if TARGET_stm32 + default n + help + Enable support for cards attached to an SDIO bus. + Select this option only if you are sure that your + board has a Broadcom wireless chip atacched to + that bus. + + config BRCMFMAC_USB + bool "Enable USB bus interface support" + depends on USB_SUPPORT + default y + help + Supported USB connected chipsets: + BCM43235, BCM43236, BCM43238 (all in revision 3 only) + BCM43143, BCM43242, BCM43566, BCM43569 + + config BRCMFMAC_PCIE + bool "Enable PCIE bus interface support" + depends on PCI_SUPPORT + default y + help + Supported PCIe connected chipsets: + BCM4354, BCM4356, BCM43567, BCM43570, BCM43602 + + endif +endef + + +define KernelPackage/b43/install + rm -rf $(1)/lib/firmware/ +ifeq ($(CONFIG_B43_OPENFIRMWARE),y) + tar xzf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)" +else + tar xjf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)" +endif + $(INSTALL_DIR) $(1)/lib/firmware/ +ifeq ($(CONFIG_B43_OPENFIRMWARE),y) + $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/" + $(INSTALL_DIR) $(1)/lib/firmware/b43-open/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/ucode5.fw $(1)/lib/firmware/b43-open/ucode5.fw + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0bsinitvals5.fw $(1)/lib/firmware/b43-open/b0g0bsinitvals5.fw + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0initvals5.fw $(1)/lib/firmware/b43-open/b0g0initvals5.fw +else + b43-fwcutter -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT) +endif +ifneq ($(CONFIG_B43_FW_SQUASH),) + b43-fwsquash.py "$(CONFIG_B43_FW_SQUASH_PHYTYPES)" "$(CONFIG_B43_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43" +endif +endef + +define KernelPackage/brcmsmac/install + $(INSTALL_DIR) $(1)/lib/firmware/brcm +ifeq ($(CONFIG_BRCMSMAC_USE_FW_FROM_WL),y) + tar xjf "$(DL_DIR)/$(PKG_BRCMSMAC_FW_SOURCE)" -C "$(PKG_BUILD_DIR)" + b43-fwcutter --brcmsmac -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_BRCMSMAC_FW_OBJECT) +endif +endef diff --git a/intel.mk b/intel.mk new file mode 100644 index 0000000..3097ec5 --- /dev/null +++ b/intel.mk @@ -0,0 +1,78 @@ +PKG_DRIVERS += iwlwifi + +config-$(call config_package,iwlwifi) += IWLWIFI IWLDVM IWLMVM IWLMLD +config-$(CONFIG_PACKAGE_IWLWIFI_DEBUG)+= IWLWIFI_DEBUG +config-$(CONFIG_PACKAGE_IWLWIFI_DEBUGFS)+= IWLWIFI_DEBUGFS + +define KernelPackage/iwlwifi + $(call KernelPackage/mac80211/Default) + DEPENDS:= +kmod-mac80211 +kmod-ptp @PCI_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT +@DRIVER_11BE_SUPPORT + TITLE:=Intel AGN Wireless support + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/iwlwifi.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/dvm/iwldvm.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/mvm/iwlmvm.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/mld/iwlmld.ko + AUTOLOAD:=$(call AutoProbe,iwlwifi iwldvm iwlmvm iwlmld) + MENU:=1 +endef + +define KernelPackage/iwlwifi/description + iwlwifi kernel module for + Intel Wireless WiFi Link 6250AGN Adapter + Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN) + Intel WiFi Link 1000BGN + Intel Wireless WiFi 5150AGN + Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN + Intel 6005 Series Wi-Fi Adapters + Intel 6030 Series Wi-Fi Adapters + Intel Wireless WiFi Link 6150BGN 2 Adapter + Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) + Intel 2000 Series Wi-Fi Adapters + Intel 7260 Wi-Fi Adapter + Intel 3160 Wi-Fi Adapter + Intel 7265 Wi-Fi Adapter + Intel 8260 Wi-Fi Adapter + Intel 3165 Wi-Fi Adapter +endef + +define KernelPackage/iwlwifi/config + if PACKAGE_kmod-iwlwifi + + config PACKAGE_IWLWIFI_DEBUG + bool "Enable full debugging output in the iwlwifi driver" + default n + help + This option will enable debug tracing output for the iwlwifi drivers + + This will result in the kernel module being ~100k larger. You can + control which debug output is sent to the kernel log by setting the + value in + + /sys/module/iwlwifi/parameters/debug + + This entry will only exist if this option is enabled. + + To set a value, simply echo an 8-byte hex value to the same file: + + % echo 0x43fff > /sys/module/iwlwifi/parameters/debug + + You can find the list of debug mask values in: + drivers/net/wireless/intel/iwlwifi/iwl-debug.h + + If this is your first time using this driver, you should say Y here + as the debug information can assist others in helping you resolve + any problems you may encounter. + + config PACKAGE_IWLWIFI_DEBUGFS + bool "iwlwifi debugfs support" + depends on PACKAGE_MAC80211_DEBUGFS + default n + help + Enable creation of debugfs files for the iwlwifi drivers. This + is a low-impact option that allows getting insight into the + driver's state at runtime. + + endif +endef + diff --git a/marvell.mk b/marvell.mk new file mode 100644 index 0000000..dbd07a8 --- /dev/null +++ b/marvell.mk @@ -0,0 +1,51 @@ +PKG_DRIVERS += \ + mwl8k mwifiex-pcie mwifiex-sdio + +config-$(call config_package,mwl8k) += MWL8K +config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE +config-$(call config_package,mwifiex-sdio) += MWIFIEX MWIFIEX_SDIO + +define KernelPackage/mwl8k + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Marvell TOPDOG 802.11 Wireless cards + URL:=https://wireless.wiki.kernel.org/en/users/drivers/mwl8k + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +mwl8k-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwl8k.ko + AUTOLOAD:=$(call AutoProbe,mwl8k) +endef + +define KernelPackage/mwl8k/description + Kernel modules for Marvell TOPDOG 802.11 Wireless cards +endef + + +define KernelPackage/mwifiex-pcie + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Marvell 802.11n/802.11ac PCIe Wireless cards + URL:=https://wireless.wiki.kernel.org/en/users/drivers/mwifiex + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11AC_SUPPORT +mwifiex-pcie-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex_pcie.ko + AUTOLOAD:=$(call AutoProbe,mwifiex_pcie) +endef + +define KernelPackage/mwifiex-pcie/description + Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards +endef + +define KernelPackage/mwifiex-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Marvell 802.11n/802.11ac SDIO Wireless cards + URL:=https://wireless.wiki.kernel.org/en/users/drivers/mwifiex + DEPENDS+= +kmod-mmc +kmod-mac80211 +@DRIVER_11AC_SUPPORT +mwifiex-sdio-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex_sdio.ko + AUTOLOAD:=$(call AutoProbe,mwifiex_sdio) +endef + +define KernelPackage/mwifiex-sdio/description + Kernel modules for Marvell 802.11n/802.11ac SDIO Wireless cards +endef + diff --git a/patches/ath/070-ath_common_config.patch b/patches/ath/070-ath_common_config.patch new file mode 100644 index 0000000..3d0b4d6 --- /dev/null +++ b/patches/ath/070-ath_common_config.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/Kconfig ++++ b/drivers/net/wireless/ath/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: ISC + config ATH_COMMON +- tristate ++ tristate "ath.ko" + depends on m + + config WLAN_VENDOR_ATH diff --git a/patches/ath/400-ath_move_debug_code.patch b/patches/ath/400-ath_move_debug_code.patch new file mode 100644 index 0000000..23b7340 --- /dev/null +++ b/patches/ath/400-ath_move_debug_code.patch @@ -0,0 +1,31 @@ +--- a/drivers/net/wireless/ath/Makefile ++++ b/drivers/net/wireless/ath/Makefile +@@ -16,10 +16,10 @@ ath-objs := main.o \ + regd.o \ + hw.o \ + key.o \ ++ debug.o \ + dfs_pattern_detector.o \ + dfs_pri_detector.o + +-ath-$(CPTCFG_ATH_DEBUG) += debug.o + ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o + + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -321,14 +321,7 @@ void _ath_dbg(struct ath_common *common, + #endif /* CPTCFG_ATH_DEBUG */ + + /** Returns string describing opmode, or NULL if unknown mode. */ +-#ifdef CPTCFG_ATH_DEBUG + const char *ath_opmode_to_string(enum nl80211_iftype opmode); +-#else +-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) +-{ +- return "UNKNOWN"; +-} +-#endif + + extern const char *ath_bus_type_strings[]; + static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype) diff --git a/patches/ath/402-ath_regd_optional.patch b/patches/ath/402-ath_regd_optional.patch new file mode 100644 index 0000000..6b1bbef --- /dev/null +++ b/patches/ath/402-ath_regd_optional.patch @@ -0,0 +1,92 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -24,6 +24,7 @@ + #include "regd_common.h" + + static int __ath_regd_init(struct ath_regulatory *reg); ++static struct reg_dmn_pair_mapping *ath_get_regpair(int regdmn); + + /* + * This is a set of common rules used by our world regulatory domains. +@@ -116,6 +117,9 @@ static const struct ieee80211_regdomain + + static bool dynamic_country_user_possible(struct ath_regulatory *reg) + { ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return true; ++ + if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) + return true; + +@@ -188,6 +192,8 @@ static bool dynamic_country_user_possibl + + static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg) + { ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return true; + if (!IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_REG_HINTS)) + return false; + if (!dynamic_country_user_possible(reg)) +@@ -345,6 +351,9 @@ ath_reg_apply_beaconing_flags(struct wip + struct ieee80211_channel *ch; + unsigned int i; + ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return; ++ + for (band = 0; band < NUM_NL80211_BANDS; band++) { + if (!wiphy->bands[band]) + continue; +@@ -379,6 +388,9 @@ ath_reg_apply_ir_flags(struct wiphy *wip + { + struct ieee80211_supported_band *sband; + ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return; ++ + sband = wiphy->bands[NL80211_BAND_2GHZ]; + if (!sband) + return; +@@ -408,6 +420,9 @@ static void ath_reg_apply_radar_flags(st + struct ieee80211_channel *ch; + unsigned int i; + ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return; ++ + if (!wiphy->bands[NL80211_BAND_5GHZ]) + return; + +@@ -640,6 +655,10 @@ ath_regd_init_wiphy(struct ath_regulator + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; ++ ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return 0; ++ + wiphy->regulatory_flags |= REGULATORY_STRICT_REG | + REGULATORY_CUSTOM_REG; + +--- a/drivers/net/wireless/ath/Kconfig ++++ b/drivers/net/wireless/ath/Kconfig +@@ -24,6 +24,9 @@ config WLAN_VENDOR_ATH + + if WLAN_VENDOR_ATH + ++config ATH_USER_REGD ++ bool "Do not enforce EEPROM regulatory restrictions" ++ + config ATH_DEBUG + bool "Atheros wireless debugging" + help +--- a/local-symbols ++++ b/local-symbols +@@ -90,6 +90,7 @@ ADM8211= + ATH_COMMON= + WLAN_VENDOR_ATH= + ATH_DEBUG= ++ATH_USER_REGD= + ATH_TRACEPOINTS= + ATH_REG_DYNAMIC_USER_REG_HINTS= + ATH_REG_DYNAMIC_USER_CERT_TESTING= diff --git a/patches/ath/403-world_regd_fixup.patch b/patches/ath/403-world_regd_fixup.patch new file mode 100644 index 0000000..ed616b7 --- /dev/null +++ b/patches/ath/403-world_regd_fixup.patch @@ -0,0 +1,84 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -44,7 +44,8 @@ static struct reg_dmn_pair_mapping *ath_ + NL80211_RRF_NO_OFDM) + + /* We allow IBSS on these on a case by case basis by regulatory domain */ +-#define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ ++#define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ ++ REG_RULE(5260-10, 5350+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) + #define ATH_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) +@@ -62,57 +63,56 @@ static struct reg_dmn_pair_mapping *ath_ + #define ATH_5GHZ_NO_MIDBAND ATH_5GHZ_5150_5350, \ + ATH_5GHZ_5725_5850 + ++#define REGD_RULES(...) \ ++ .reg_rules = { __VA_ARGS__ }, \ ++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ })) ++ + /* Can be used for: + * 0x60, 0x61, 0x62 */ + static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { +- .n_reg_rules = 5, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_ALL, + ATH_5GHZ_ALL, +- } ++ ) + }; + + /* Can be used by 0x63 and 0x65 */ + static const struct ieee80211_regdomain ath_world_regdom_63_65 = { +- .n_reg_rules = 4, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_2GHZ_CH12_13, + ATH_5GHZ_NO_MIDBAND, +- } ++ ) + }; + + /* Can be used by 0x64 only */ + static const struct ieee80211_regdomain ath_world_regdom_64 = { +- .n_reg_rules = 3, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_5GHZ_NO_MIDBAND, +- } ++ ) + }; + + /* Can be used by 0x66 and 0x69 */ + static const struct ieee80211_regdomain ath_world_regdom_66_69 = { +- .n_reg_rules = 3, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_5GHZ_ALL, +- } ++ ) + }; + + /* Can be used by 0x67, 0x68, 0x6A and 0x6C */ + static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { +- .n_reg_rules = 4, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_2GHZ_CH12_13, + ATH_5GHZ_ALL, +- } ++ ) + }; + + static bool dynamic_country_user_possible(struct ath_regulatory *reg) diff --git a/patches/ath/404-regd_no_assoc_hints.patch b/patches/ath/404-regd_no_assoc_hints.patch new file mode 100644 index 0000000..e9b83b8 --- /dev/null +++ b/patches/ath/404-regd_no_assoc_hints.patch @@ -0,0 +1,19 @@ +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -3365,6 +3365,8 @@ void regulatory_hint_country_ie(struct w + enum environment_cap env = ENVIRON_ANY; + struct regulatory_request *request = NULL, *lr; + ++ return; ++ + /* IE len must be evenly divisible by 2 */ + if (country_ie_len & 0x01) + return; +@@ -3614,6 +3616,7 @@ static bool is_wiphy_all_set_reg_flag(en + + void regulatory_hint_disconnect(void) + { ++ return; + /* Restore of regulatory settings is not required when wiphy(s) + * ignore IE from connected access point but clearance of beacon hints + * is required when wiphy(s) supports beacon hints. diff --git a/patches/ath/405-ath_regd_us.patch b/patches/ath/405-ath_regd_us.patch new file mode 100644 index 0000000..6723721 --- /dev/null +++ b/patches/ath/405-ath_regd_us.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/wireless/ath/regd_common.h ++++ b/drivers/net/wireless/ath/regd_common.h +@@ -32,6 +32,7 @@ enum EnumRd { + FCC2_WORLD = 0x21, + FCC2_ETSIC = 0x22, + FCC6_WORLD = 0x23, ++ FCC3_FCCA_2 = 0x2A, + FRANCE_RES = 0x31, + FCC3_FCCA = 0x3A, + FCC3_WORLD = 0x3B, +@@ -173,6 +174,7 @@ static struct reg_dmn_pair_mapping regDo + {FCC2_WORLD, CTL_FCC, CTL_ETSI}, + {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC3_FCCA, CTL_FCC, CTL_FCC}, ++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC}, + {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC3_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC4_FCCA, CTL_FCC, CTL_FCC}, +@@ -486,6 +488,7 @@ static struct country_code_to_enum_rd al + {CTRY_UAE, NULL1_WORLD, "AE"}, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, + {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, ++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"}, + {CTRY_UNITED_STATES2, FCC3_FCCA, "US"}, + {CTRY_UNITED_STATES3, FCC3_FCCA, "US"}, + /* This "PS" is for US public safety actually... to support this we diff --git a/patches/ath/406-ath_relax_default_regd.patch b/patches/ath/406-ath_relax_default_regd.patch new file mode 100644 index 0000000..ee4e461 --- /dev/null +++ b/patches/ath/406-ath_relax_default_regd.patch @@ -0,0 +1,51 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -115,6 +115,16 @@ static const struct ieee80211_regdomain + ) + }; + ++static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) ++{ ++ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; ++} ++ ++static bool is_default_regd(struct ath_regulatory *reg) ++{ ++ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT; ++} ++ + static bool dynamic_country_user_possible(struct ath_regulatory *reg) + { + if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) +@@ -123,6 +133,9 @@ static bool dynamic_country_user_possibl + if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) + return true; + ++ if (is_default_regd(reg)) ++ return true; ++ + switch (reg->country_code) { + case CTRY_UNITED_STATES: + case CTRY_JAPAN1: +@@ -208,11 +221,6 @@ static inline bool is_wwr_sku(u16 regd) + (regd == WORLD)); + } + +-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) +-{ +- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; +-} +- + bool ath_is_world_regd(struct ath_regulatory *reg) + { + return is_wwr_sku(ath_regd_get_eepromRD(reg)); +@@ -659,6 +667,9 @@ ath_regd_init_wiphy(struct ath_regulator + if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) + return 0; + ++ if (is_default_regd(reg)) ++ return 0; ++ + wiphy->regulatory_flags |= REGULATORY_STRICT_REG | + REGULATORY_CUSTOM_REG; + diff --git a/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch b/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch new file mode 100644 index 0000000..abadadf --- /dev/null +++ b/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch @@ -0,0 +1,56 @@ +--- a/drivers/net/wireless/ath/ath5k/pci.c ++++ b/drivers/net/wireless/ath/ath5k/pci.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include "../ath.h" + #include "ath5k.h" + #include "debug.h" +@@ -73,7 +74,7 @@ static void ath5k_pci_read_cachesize(str + } + + /* +- * Read from eeprom ++ * Read from eeprom or platform_data + */ + static bool + ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) +@@ -81,6 +82,19 @@ ath5k_pci_eeprom_read(struct ath_common + struct ath5k_hw *ah = common->ah; + u32 status, timeout; + ++ struct ath5k_platform_data *pdata = NULL; ++ ++ if (ah->pdev) ++ pdata = ah->pdev->dev.platform_data; ++ ++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) { ++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS) ++ return false; ++ ++ *data = pdata->eeprom_data[offset]; ++ return true; ++ } ++ + /* + * Initialize EEPROM access + */ +@@ -124,6 +138,16 @@ static int ath5k_pci_eeprom_read_mac(str + u16 data; + int octet; + ++ struct ath5k_platform_data *pdata = NULL; ++ ++ if (ah->pdev) ++ pdata = ah->pdev->dev.platform_data; ++ ++ if (pdata && pdata->macaddr) { ++ memcpy(mac, pdata->macaddr, ETH_ALEN); ++ return 0; ++ } ++ + AR5K_EEPROM_READ(0x20, data); + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { diff --git a/patches/ath10k/080-ath10k_thermal_config.patch b/patches/ath10k/080-ath10k_thermal_config.patch new file mode 100644 index 0000000..0c631f6 --- /dev/null +++ b/patches/ath10k/080-ath10k_thermal_config.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/ath/ath10k/Kconfig ++++ b/drivers/net/wireless/ath/ath10k/Kconfig +@@ -94,6 +94,12 @@ config ATH10K_TRACING + help + Select this to ath10k use tracing infrastructure. + ++config ATH10K_THERMAL ++ bool "Atheros ath10k thermal monitoring support" ++ depends on THERMAL ++ ---help--- ++ Select this to ath10k use hwmon for thermal measurement. ++ + config ATH10K_DFS_CERTIFIED + bool "Atheros DFS support for certified platforms" + depends on ATH10K && CFG80211_CERTIFICATION_ONUS +--- a/drivers/net/wireless/ath/ath10k/Makefile ++++ b/drivers/net/wireless/ath/ath10k/Makefile +@@ -18,7 +18,7 @@ ath10k_core-y += mac.o \ + ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o + ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o +-ath10k_core-$(CONFIG_THERMAL) += thermal.o ++ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o + ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o + ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o + ath10k_core-$(CONFIG_PM) += wow.o +--- a/drivers/net/wireless/ath/ath10k/thermal.h ++++ b/drivers/net/wireless/ath/ath10k/thermal.h +@@ -25,7 +25,7 @@ struct ath10k_thermal { + int temperature; + }; + +-#if IS_REACHABLE(CONFIG_THERMAL) ++#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL) + int ath10k_thermal_register(struct ath10k *ar); + void ath10k_thermal_unregister(struct ath10k *ar); + void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); +--- a/local-symbols ++++ b/local-symbols +@@ -150,6 +150,7 @@ ATH10K_DEBUG= + ATH10K_DEBUGFS= + ATH10K_LEDS= + ATH10K_SPECTRAL= ++ATH10K_THERMAL= + ATH10K_TRACING= + ATH10K_DFS_CERTIFIED= + WCN36XX= diff --git a/patches/ath10k/921-ath10k_init_devices_synchronously.patch b/patches/ath10k/921-ath10k_init_devices_synchronously.patch new file mode 100644 index 0000000..1fb9d50 --- /dev/null +++ b/patches/ath10k/921-ath10k_init_devices_synchronously.patch @@ -0,0 +1,33 @@ +From: Sven Eckelmann +Date: Tue, 18 Nov 2014 12:29:28 +0100 +Subject: [PATCH] ath10k: Don't initialize devices asynchronously + +OpenWrt requires all PHYs to be initialized to create the configuration files +during bootup. ath10k violates this because it delays the creation of the PHY +to a not well defined point in the future. + +Forcing the work to be done immediately works around this problem but may also +delay the boot when firmware images cannot be found. + +Signed-off-by: Sven Eckelmann +--- + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -3546,6 +3546,16 @@ int ath10k_core_register(struct ath10k * + + queue_work(ar->workqueue, &ar->register_work); + ++ /* OpenWrt requires all PHYs to be initialized to create the ++ * configuration files during bootup. ath10k violates this ++ * because it delays the creation of the PHY to a not well defined ++ * point in the future. ++ * ++ * Forcing the work to be done immediately works around this problem ++ * but may also delay the boot when firmware images cannot be found. ++ */ ++ flush_workqueue(ar->workqueue); ++ + return 0; + } + EXPORT_SYMBOL(ath10k_core_register); diff --git a/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch b/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch new file mode 100644 index 0000000..89d0c5c --- /dev/null +++ b/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -9951,6 +9951,21 @@ static int ath10k_mac_init_rd(struct ath + return 0; + } + ++#ifdef CPTCFG_MAC80211_LEDS ++static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = { ++ { .throughput = 0 * 1024, .blink_time = 334 }, ++ { .throughput = 1 * 1024, .blink_time = 260 }, ++ { .throughput = 2 * 1024, .blink_time = 220 }, ++ { .throughput = 5 * 1024, .blink_time = 190 }, ++ { .throughput = 10 * 1024, .blink_time = 170 }, ++ { .throughput = 25 * 1024, .blink_time = 150 }, ++ { .throughput = 54 * 1024, .blink_time = 130 }, ++ { .throughput = 120 * 1024, .blink_time = 110 }, ++ { .throughput = 265 * 1024, .blink_time = 80 }, ++ { .throughput = 586 * 1024, .blink_time = 50 }, ++}; ++#endif ++ + int ath10k_mac_register(struct ath10k *ar) + { + static const u32 cipher_suites[] = { +@@ -10313,6 +10328,12 @@ int ath10k_mac_register(struct ath10k *a + + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + ++#ifdef CPTCFG_MAC80211_LEDS ++ ieee80211_create_tpt_led_trigger(ar->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, ++ ARRAY_SIZE(ath10k_tpt_blink)); ++#endif ++ + ret = ieee80211_register_hw(ar->hw); + if (ret) { + ath10k_err(ar, "failed to register ieee80211: %d\n", ret); diff --git a/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch b/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch new file mode 100644 index 0000000..938be27 --- /dev/null +++ b/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch @@ -0,0 +1,51 @@ +From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Fri, 22 Jun 2018 18:59:44 +0200 +Subject: [PATCH] ath10k: use tpt LED trigger by default + +Use the tpt LED trigger for each created phy led. Ths way LEDs attached +to the ath10k GPIO pins are indicating the phy status and blink on +traffic. + +Signed-off-by: Mathias Kresin +--- + drivers/net/wireless/ath/ath10k/core.h | 4 ++++ + drivers/net/wireless/ath/ath10k/leds.c | 4 +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -1315,6 +1315,10 @@ struct ath10k { + s32 tx_power_2g_limit; + s32 tx_power_5g_limit; + ++#ifdef CPTCFG_MAC80211_LEDS ++ const char *led_default_trigger; ++#endif ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath10k/leds.c ++++ b/drivers/net/wireless/ath/ath10k/leds.c +@@ -70,7 +70,7 @@ int ath10k_leds_register(struct ath10k * + + ar->leds.cdev.name = ar->leds.label; + ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; +- ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; ++ ar->leds.cdev.default_trigger = ar->led_default_trigger; + + ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); + if (ret) +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -10329,7 +10329,7 @@ int ath10k_mac_register(struct ath10k *a + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + + #ifdef CPTCFG_MAC80211_LEDS +- ieee80211_create_tpt_led_trigger(ar->hw, ++ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, + ARRAY_SIZE(ath10k_tpt_blink)); + #endif diff --git a/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch new file mode 100644 index 0000000..a976502 --- /dev/null +++ b/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch @@ -0,0 +1,101 @@ +From: Sven Eckelmann +Date: Wed, 28 Nov 2018 16:16:27 +0100 +Subject: ath10k: adjust tx power reduction for US regulatory domain + +FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): + +> (4) The conducted output power limit +> specified in paragraph (b) of this section +> is based on the use of antennas +> with directional gains that do not exceed +> 6 dBi. Except as shown in paragraph +> (c) of this section, if transmitting +> antennas of directional gain greater +> than 6 dBi are used, the conducted +> output power from the intentional radiator +> shall be reduced below the stated +> values in paragraphs (b)(1), (b)(2), +> and (b)(3) of this section, as appropriate, +> by the amount in dB that the +> directional gain of the antenna exceeds +> 6 dBi. + +https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf + +Signed-off-by: Sven Eckelmann + +Forwarded: no + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -1043,6 +1043,40 @@ static inline int ath10k_vdev_delete_syn + return 0; + } + ++static u32 ath10k_get_max_antenna_gain(struct ath10k *ar, ++ u32 ch_max_antenna_gain) ++{ ++ u32 max_antenna_gain; ++ ++ if (ar->dfs_detector && ar->dfs_detector->region == NL80211_DFS_FCC) { ++ /* FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): ++ * ++ * > (4) The conducted output power limit ++ * > specified in paragraph (b) of this section ++ * > is based on the use of antennas ++ * > with directional gains that do not exceed ++ * > 6 dBi. Except as shown in paragraph ++ * > (c) of this section, if transmitting ++ * > antennas of directional gain greater ++ * > than 6 dBi are used, the conducted ++ * > output power from the intentional radiator ++ * > shall be reduced below the stated ++ * > values in paragraphs (b)(1), (b)(2), ++ * > and (b)(3) of this section, as appropriate, ++ * > by the amount in dB that the ++ * > directional gain of the antenna exceeds ++ * > 6 dBi. ++ * ++ * https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf ++ */ ++ max_antenna_gain = 6; ++ } else { ++ max_antenna_gain = 0; ++ } ++ ++ return max(ch_max_antenna_gain, max_antenna_gain); ++} ++ + static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) + { + struct cfg80211_chan_def *chandef = NULL; +@@ -1075,7 +1109,8 @@ static int ath10k_monitor_vdev_start(str + arg.channel.min_power = 0; + arg.channel.max_power = channel->max_power * 2; + arg.channel.max_reg_power = channel->max_reg_power * 2; +- arg.channel.max_antenna_gain = channel->max_antenna_gain; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); + + reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); +@@ -1521,7 +1556,8 @@ static int ath10k_vdev_start_restart(str + arg.channel.min_power = 0; + arg.channel.max_power = chandef->chan->max_power * 2; + arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; +- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ chandef->chan->max_antenna_gain); + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; +@@ -3452,7 +3488,8 @@ static int ath10k_update_channel_list(st + ch->min_power = 0; + ch->max_power = channel->max_power * 2; + ch->max_reg_power = channel->max_reg_power * 2; +- ch->max_antenna_gain = channel->max_antenna_gain; ++ ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any diff --git a/patches/ath10k/982-ath10k-disable-caldata-prefetch-for-sdio-bus.patch b/patches/ath10k/982-ath10k-disable-caldata-prefetch-for-sdio-bus.patch new file mode 100644 index 0000000..4c23299 --- /dev/null +++ b/patches/ath10k/982-ath10k-disable-caldata-prefetch-for-sdio-bus.patch @@ -0,0 +1,24 @@ +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -3554,7 +3554,8 @@ int ath10k_core_register(struct ath10k * + * Forcing the work to be done immediately works around this problem + * but may also delay the boot when firmware images cannot be found. + */ +- flush_workqueue(ar->workqueue); ++ if (ar->hif.bus != ATH10K_BUS_SDIO) ++ flush_workqueue(ar->workqueue); + + return 0; + } +--- a/drivers/net/wireless/ath/ath10k/debug.c ++++ b/drivers/net/wireless/ath/ath10k/debug.c +@@ -1262,6 +1262,9 @@ static int ath10k_debug_cal_data_fetch(s + if (ar->hw_params.cal_data_len == 0) + return -EOPNOTSUPP; + ++ if (ar->hif.bus == ATH10K_BUS_SDIO) ++ return -EINVAL; ++ + hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); + + ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); diff --git a/patches/ath10k/983-ath10k-allow-vht-on-2g.patch b/patches/ath10k/983-ath10k-allow-vht-on-2g.patch new file mode 100644 index 0000000..36ab6ae --- /dev/null +++ b/patches/ath10k/983-ath10k-allow-vht-on-2g.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -5054,6 +5054,7 @@ static void ath10k_mac_setup_ht_vht_cap( + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; + band->ht_cap = ht_cap; ++ band->vht_cap = vht_cap; + } + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; diff --git a/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch b/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch new file mode 100644 index 0000000..6cb1038 --- /dev/null +++ b/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch @@ -0,0 +1,37 @@ +From 22fb5991a44c78ff18ec0082dc90c809356eb893 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 27 Sep 2020 19:23:35 +0200 +Subject: [PATCH 1/2] ath10k: Try to get mac-address from dts + +Most of embedded device that have the ath10k wifi integrated store the +mac-address in nvmem partitions. Try to fetch the mac-address using the +standard 'of_get_mac_address' than in all the check also try to fetch the +address using the nvmem api searching for a defined 'mac-address' cell. +Mac-address defined in the dts have priority than any other address found. + +Tested-on: QCA9984 hw1.0 PCI 10.4 + +Signed-off-by: Ansuel Smith +--- + drivers/net/wireless/ath/ath10k/core.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3418,6 +3419,8 @@ static int ath10k_core_probe_fw(struct a + + device_get_mac_address(ar->dev, ar->mac_addr); + ++ of_get_mac_address(ar->dev->of_node, ar->mac_addr); ++ + ret = ath10k_core_init_firmware_features(ar); + if (ret) { + ath10k_err(ar, "fatal problem with firmware features: %d\n", diff --git a/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch b/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch new file mode 100644 index 0000000..f83a847 --- /dev/null +++ b/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch @@ -0,0 +1,28 @@ +From f7d6edafe4358e3880a26775cfde4cd5c71ba063 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Wed, 5 Jul 2023 01:30:29 +0200 +Subject: [PATCH] ath10k: always use mac80211 loss detection + +ath10k does not report excessive loss in case of broken block-ack +sessions. The loss is communicated to the host-os, but ath10k does not +trigger a low-ack events by itself. + +The mac80211 framework for loss detection however detects this +circumstance well in case of ath10k. So use it regardless of ath10k's +own loss detection mechanism. + +Signed-off-by: David Bauer +--- + drivers/net/wireless/ath/ath10k/mac.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -10122,7 +10122,6 @@ int ath10k_mac_register(struct ath10k *a + ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA); + ieee80211_hw_set(ar->hw, QUEUE_CONTROL); + ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); +- ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); + + if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) + ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL); diff --git a/patches/ath10k/990-ath10k-small-buffers.patch b/patches/ath10k/990-ath10k-small-buffers.patch new file mode 100644 index 0000000..755982a --- /dev/null +++ b/patches/ath10k/990-ath10k-small-buffers.patch @@ -0,0 +1,64 @@ +--- a/drivers/net/wireless/ath/ath10k/htt.h ++++ b/drivers/net/wireless/ath/ath10k/htt.h +@@ -236,7 +236,11 @@ enum htt_rx_ring_flags { + }; + + #define HTT_RX_RING_SIZE_MIN 128 ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + #define HTT_RX_RING_SIZE_MAX 2048 ++#else ++#define HTT_RX_RING_SIZE_MAX 512 ++#endif + #define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX + #define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1) + #define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1) +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -132,7 +132,11 @@ static const struct ce_attr pci_host_ce_ + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 512, ++#else ++ .dest_nentries = 128, ++#endif + .recv_cb = ath10k_pci_htt_htc_rx_cb, + }, + +@@ -141,7 +145,11 @@ static const struct ce_attr pci_host_ce_ + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 128, ++#else ++ .dest_nentries = 64, ++#endif + .recv_cb = ath10k_pci_htc_rx_cb, + }, + +@@ -168,7 +176,11 @@ static const struct ce_attr pci_host_ce_ + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 512, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 512, ++#else ++ .dest_nentries = 128, ++#endif + .recv_cb = ath10k_pci_htt_rx_cb, + }, + +@@ -193,7 +205,11 @@ static const struct ce_attr pci_host_ce_ + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 128, ++#else ++ .dest_nentries = 96, ++#endif + .recv_cb = ath10k_pci_pktlog_rx_cb, + }, + diff --git a/patches/ath10k/991-ath10k-support-flush_sta-method.patch b/patches/ath10k/991-ath10k-support-flush_sta-method.patch new file mode 100644 index 0000000..a0f6eed --- /dev/null +++ b/patches/ath10k/991-ath10k-support-flush_sta-method.patch @@ -0,0 +1,70 @@ +From: Zhi-Jun You +Date: Wed, 6 Aug 2025 15:00:05 +0800 +Subject: [RFC PATCH] wifi: ath10k: support flush_sta method + + +When a STA is marked as no longer authorized, if the driver doesn't +implement flush_sta(), mac80211 calls ieee80211_flush_queues() to +flush hardware queues to avoid sending unencrypted frames. + +This has became a problem for ath10k because ieee80211_flush_queues() +will stop all traffic and call ath10k_flush, which waits until the +whole HW queue is empty. In a busy environment this will trigger a +timeout warning and stalls other STAs. + +Fix this by implementing flush_sta method using WMI command to flush +frames of a specific STA. +Flushed frames will be marked as discard in tx complete indication. + +ops->flush_sta will be set to NULL if htt.disable_tx_comp is set to +true. + +Tested-on: QCA9984 hw1.0 PCI 10.4-3.9.0.2-00157 + +Signed-off-by: Zhi-Jun You +Tested-by: Florian Maurer +--- + drivers/net/wireless/ath/ath10k/mac.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -8166,6 +8166,20 @@ static void ath10k_flush(struct ieee8021 + mutex_unlock(&ar->conf_mutex); + } + ++static void ath10k_mac_op_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct ath10k_vif *arvif = (void *)vif->drv_priv; ++ struct ath10k *ar = hw->priv; ++ u32 bitmap = 0xFFFFFFFF; ++ int ret = 0; ++ ++ ret = ath10k_wmi_peer_flush(ar, arvif->vdev_id, sta->addr, bitmap); ++ if (ret) ++ ath10k_warn(ar, "failed to flush sta (sta %pM)\n", ++ sta->addr); ++} ++ + /* TODO: Implement this function properly + * For now it is needed to reply to Probe Requests in IBSS mode. + * Probably we need this information from FW. +@@ -9513,6 +9527,7 @@ static const struct ieee80211_ops ath10k + .set_rts_threshold = ath10k_set_rts_threshold, + .set_frag_threshold = ath10k_mac_op_set_frag_threshold, + .flush = ath10k_flush, ++ .flush_sta = ath10k_mac_op_flush_sta, + .tx_last_beacon = ath10k_tx_last_beacon, + .set_antenna = ath10k_set_antenna, + .get_antenna = ath10k_get_antenna, +@@ -10334,6 +10349,9 @@ int ath10k_mac_register(struct ath10k *a + if (!ar->hw_params.hw_ops->set_coverage_class) + ar->ops->set_coverage_class = NULL; + ++ if (ar->htt.disable_tx_comp) ++ ar->ops->flush_sta = NULL; ++ + ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, + ath10k_reg_notifier); + if (ret) { diff --git a/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch b/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch new file mode 100644 index 0000000..c2f3f73 --- /dev/null +++ b/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch @@ -0,0 +1,164 @@ +From 534a5f99d589cfa6b244b4433c192b6a278a67ff Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 5 Nov 2022 20:15:40 +0100 +Subject: [PATCH] wifi: ath11k: use unique QRTR instance ID + +Currently, trying to use AHB + PCI/MHI cards or multiple PCI/MHI cards +will cause a clash in the QRTR instance node ID and prevent the driver +from talking via QMI to the card and thus initializing it with: +[ 9.836329] ath11k c000000.wifi: host capability request failed: 1 90 +[ 9.842047] ath11k c000000.wifi: failed to send qmi host cap: -22 + +So, in order to allow for this combination of cards, especially AHB + PCI +cards like IPQ8074 + QCN9074 (Used by me and tested on) set the desired +QRTR instance ID offset by calculating a unique one based on PCI domain +and bus ID-s and writing it to bits 7-0 of BHI_ERRDBG2 MHI register by +using the SBL state callback that is added as part of the series. +We also have to make sure that new QRTR offset is added on top of the +default QRTR instance ID-s that are currently used in the driver. + +This finally allows using AHB + PCI or multiple PCI cards on the same +system. + +Since this is not supported on QCA6390 and like, its limited to QCN9074 +which is known to support changing QRTR instance ID. + +Before: +root@OpenWrt:/# qrtr-lookup + Service Version Instance Node Port + 1054 1 0 7 1 + 69 1 2 7 3 ATH10k WLAN firmware service + +After: +root@OpenWrt:/# qrtr-lookup + Service Version Instance Node Port + 1054 1 0 7 1 + 69 1 2 7 3 ATH10k WLAN firmware service + 15 1 0 8 1 Test service + 69 1 8 8 2 ATH10k WLAN firmware service + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/mhi.c | 49 ++++++++++++++++++--------- + drivers/net/wireless/ath/ath11k/mhi.h | 3 ++ + drivers/net/wireless/ath/ath11k/pci.c | 9 ++++- + 3 files changed, 44 insertions(+), 17 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -239,6 +239,34 @@ static void ath11k_mhi_op_runtime_put(st + { + } + ++static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl, ++ void __iomem *addr, ++ u32 *out) ++{ ++ *out = readl(addr); ++ ++ return 0; ++} ++ ++static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, ++ void __iomem *addr, ++ u32 val) ++{ ++ writel(val, addr); ++} ++ ++static void ath11k_mhi_qrtr_instance_set(struct mhi_controller *mhi_cntrl) ++{ ++ struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); ++ ++ if (ab->hw_rev == ATH11K_HW_QCN9074_HW10) { ++ ath11k_mhi_op_write_reg(mhi_cntrl, ++ mhi_cntrl->bhi + BHI_ERRDBG2, ++ FIELD_PREP(QRTR_INSTANCE_MASK, ++ ab->qmi.service_ins_id - ab->hw_params.qmi_service_ins_id)); ++ } ++} ++ + static char *ath11k_mhi_op_callback_to_str(enum mhi_callback reason) + { + switch (reason) { +@@ -260,6 +288,8 @@ static char *ath11k_mhi_op_callback_to_s + return "MHI_CB_FATAL_ERROR"; + case MHI_CB_BW_REQ: + return "MHI_CB_BW_REQ"; ++ case MHI_CB_EE_SBL_MODE: ++ return "MHI_CB_EE_SBL_MODE"; + default: + return "UNKNOWN"; + } +@@ -290,6 +320,9 @@ static void ath11k_mhi_op_status_cb(stru + queue_work(ab->workqueue_aux, &ab->reset_work); + + break; ++ case MHI_CB_EE_SBL_MODE: ++ ath11k_mhi_qrtr_instance_set(mhi_cntrl); ++ break; + default: + break; + } +@@ -297,22 +330,6 @@ static void ath11k_mhi_op_status_cb(stru + ab_pci->mhi_pre_cb = cb; + } + +-static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl, +- void __iomem *addr, +- u32 *out) +-{ +- *out = readl(addr); +- +- return 0; +-} +- +-static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, +- void __iomem *addr, +- u32 val) +-{ +- writel(val, addr); +-} +- + static int ath11k_mhi_read_addr_from_dt(struct mhi_controller *mhi_ctrl) + { + struct device_node *np; +--- a/drivers/net/wireless/ath/ath11k/mhi.h ++++ b/drivers/net/wireless/ath/ath11k/mhi.h +@@ -17,6 +17,9 @@ + #define MHICTRL 0x38 + #define MHICTRL_RESET_MASK 0x2 + ++#define BHI_ERRDBG2 0x38 ++#define QRTR_INSTANCE_MASK GENMASK(7, 0) ++ + int ath11k_mhi_start(struct ath11k_pci *ar_pci); + void ath11k_mhi_stop(struct ath11k_pci *ar_pci, bool is_suspend); + int ath11k_mhi_register(struct ath11k_pci *ar_pci); +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -376,13 +376,20 @@ static void ath11k_pci_sw_reset(struct a + static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab) + { + struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; ++ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); ++ struct pci_bus *bus = ab_pci->pdev->bus; + + cfg->tgt_ce = ab->hw_params.target_ce_config; + cfg->tgt_ce_len = ab->hw_params.target_ce_count; + + cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map; + cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len; +- ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; ++ ++ if (ab->hw_rev == ATH11K_HW_QCN9074_HW10) { ++ ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id + ++ (((pci_domain_nr(bus) & 0xF) << 4) | (bus->number & 0xF)); ++ } else ++ ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; + + ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2, + &cfg->shadow_reg_v2_len); diff --git a/patches/ath11k/201-wifi-ath11k-Support-setting-bdf-addr-and-caldb-addr-.patch b/patches/ath11k/201-wifi-ath11k-Support-setting-bdf-addr-and-caldb-addr-.patch new file mode 100644 index 0000000..a1ba8ec --- /dev/null +++ b/patches/ath11k/201-wifi-ath11k-Support-setting-bdf-addr-and-caldb-addr-.patch @@ -0,0 +1,62 @@ +From 824dde8652815aa67b4e2bf2d8a9455a8ef82b8f Mon Sep 17 00:00:00 2001 +From: Ziyang Huang +Date: Thu, 29 Jun 2023 06:12:45 +0000 +Subject: [PATCH] wifi: ath11k: Support setting bdf-addr and caldb-addr via DT + +Signed-off-by: Ziyang Huang +--- + drivers/net/wireless/ath/ath11k/qmi.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2041,6 +2041,7 @@ static int ath11k_qmi_assign_target_mem_ + struct device_node *hremote_node = NULL; + struct resource res; + u32 host_ddr_sz; ++ u32 addr; + int i, idx, ret; + + for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { +@@ -2080,7 +2081,9 @@ static int ath11k_qmi_assign_target_mem_ + idx++; + break; + case BDF_MEM_REGION_TYPE: +- ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr; ++ if (of_property_read_u32(dev->of_node, "qcom,bdf-addr", &addr)) ++ addr = ab->hw_params.bdf_addr; ++ ab->qmi.target_mem[idx].paddr = addr; + ab->qmi.target_mem[idx].iaddr = NULL; + ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; + ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; +@@ -2102,8 +2105,9 @@ static int ath11k_qmi_assign_target_mem_ + if (!ab->qmi.target_mem[idx].iaddr) + return -EIO; + } else { +- ab->qmi.target_mem[idx].paddr = +- ATH11K_QMI_CALDB_ADDRESS; ++ if (of_property_read_u32(dev->of_node, "qcom,caldb-addr", &addr)) ++ addr = ATH11K_QMI_CALDB_ADDRESS; ++ ab->qmi.target_mem[idx].paddr = addr; + ab->qmi.target_mem[idx].iaddr = NULL; + } + } else { +@@ -2309,6 +2313,7 @@ static int ath11k_qmi_load_file_target_m + struct qmi_wlanfw_bdf_download_resp_msg_v01 resp; + struct qmi_txn txn; + const u8 *temp = data; ++ u32 addr; + void __iomem *bdf_addr = NULL; + int ret = 0; + u32 remaining = len; +@@ -2320,7 +2325,9 @@ static int ath11k_qmi_load_file_target_m + memset(&resp, 0, sizeof(resp)); + + if (ab->hw_params.fixed_bdf_addr) { +- bdf_addr = ioremap(ab->hw_params.bdf_addr, ab->hw_params.fw.board_size); ++ if(of_property_read_u32(ab->dev->of_node, "qcom,bdf-addr", &addr)) ++ addr = ab->hw_params.bdf_addr; ++ bdf_addr = ioremap(addr, ab->hw_params.fw.board_size); + if (!bdf_addr) { + ath11k_warn(ab, "qmi ioremap error for bdf_addr\n"); + ret = -EIO; diff --git a/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch b/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch new file mode 100644 index 0000000..264e9eb --- /dev/null +++ b/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch @@ -0,0 +1,66 @@ +From 703d6551f71e7290619d6effe2a25a64e10538b7 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 15 Dec 2022 12:20:52 +0100 +Subject: [PATCH] ath11k: control thermal support via symbol + +Currently, thermal support will get built if CONFIG_THERMAL is reachable, +however this is not suitable for OpenWrt as with ALL_KMODS being set to y +ATH11K_THERMAL wont get selected and so hwmon and thermal kmods wont get +pulled in resulting in a build-failure. + +So, to avoid that, lets do what is already done for ath10k and add a +config symbol into backports for enabling thermal support. + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/Kconfig | 7 +++++++ + drivers/net/wireless/ath/ath11k/Makefile | 2 +- + drivers/net/wireless/ath/ath11k/thermal.h | 2 +- + local-symbols | 1 + + 4 files changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/Kconfig ++++ b/drivers/net/wireless/ath/ath11k/Kconfig +@@ -62,3 +62,10 @@ config ATH11K_SPECTRAL + Enable ath11k spectral scan support + + Say Y to enable access to the FFT/spectral data via debugfs. ++ ++config ATH11K_THERMAL ++ bool "ath11k thermal sensors and throttling support" ++ depends on ATH11K ++ depends on THERMAL ++ help ++ Enable ath11k thermal sensors and throttling support. +--- a/drivers/net/wireless/ath/ath11k/Makefile ++++ b/drivers/net/wireless/ath/ath11k/Makefile +@@ -24,7 +24,7 @@ ath11k-y += core.o \ + ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath11k-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath11k-$(CPTCFG_ATH11K_TRACING) += trace.o +-ath11k-$(CONFIG_THERMAL) += thermal.o ++ath11k-$(CPTCFG_ATH11K_THERMAL) += thermal.o + ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o + ath11k-$(CONFIG_PM) += wow.o + ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o +--- a/drivers/net/wireless/ath/ath11k/thermal.h ++++ b/drivers/net/wireless/ath/ath11k/thermal.h +@@ -26,7 +26,7 @@ struct ath11k_thermal { + int temperature; + }; + +-#if IS_REACHABLE(CONFIG_THERMAL) ++#if IS_REACHABLE(CPTCFG_ATH11K_THERMAL) + int ath11k_thermal_register(struct ath11k_base *ab); + void ath11k_thermal_unregister(struct ath11k_base *ab); + int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state); +--- a/local-symbols ++++ b/local-symbols +@@ -162,6 +162,7 @@ ATH11K_DEBUG= + ATH11K_DEBUGFS= + ATH11K_TRACING= + ATH11K_SPECTRAL= ++ATH11K_THERMAL= + ATH12K= + ATH12K_AHB= + ATH12K_DEBUG= diff --git a/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch b/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch new file mode 100644 index 0000000..fa9c005 --- /dev/null +++ b/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch @@ -0,0 +1,75 @@ +From fb1c40c225cbc413d82c872dd8c8af3469b2b921 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 16 Dec 2022 17:17:52 +0100 +Subject: [PATCH] ath11k: support setting FW memory mode via DT + +ath11k is really memory intensive for devices with less that 1GB of RAM, +so lets allow saving a significant amount of memory by setting the FW to +Mode-1 via DTS for devices that need it. + +However the drawback is reduced number of VDEV-s and peers which is a +reasonable tradeoff. + +Mode-2 allows for further reduction, but it has further restrictions. + +While we are here, lets add a print to be able to easily determine what +FW memory mode is being used. + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/core.c | 28 ++++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -37,7 +37,7 @@ bool ath11k_ftm_mode; + module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444); + MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); + +-static const struct ath11k_hw_params ath11k_hw_params[] = { ++static struct ath11k_hw_params ath11k_hw_params[] = { + { + .hw_rev = ATH11K_HW_IPQ8074, + .name = "ipq8074 hw2.0", +@@ -2481,7 +2481,8 @@ static void ath11k_core_reset(struct wor + static int ath11k_init_hw_params(struct ath11k_base *ab) + { + const struct ath11k_hw_params *hw_params = NULL; +- int i; ++ u32 fw_mem_mode; ++ int i, ret; + + for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) { + hw_params = &ath11k_hw_params[i]; +@@ -2497,7 +2498,31 @@ static int ath11k_init_hw_params(struct + + ab->hw_params = *hw_params; + ++ ret = of_property_read_u32(ab->dev->of_node, ++ "qcom,ath11k-fw-memory-mode", ++ &fw_mem_mode); ++ if (!ret) { ++ if (fw_mem_mode == 0) { ++ ab->hw_params.fw_mem_mode = 0; ++ ab->hw_params.num_vdevs = 16 + 1; ++ ab->hw_params.num_peers = 512; ++ } ++ else if (fw_mem_mode == 1) { ++ ab->hw_params.fw_mem_mode = 1; ++ ab->hw_params.num_vdevs = 8; ++ ab->hw_params.num_peers = 128; ++ } else if (fw_mem_mode == 2) { ++ ab->hw_params.fw_mem_mode = 2; ++ ab->hw_params.num_vdevs = 8; ++ ab->hw_params.num_peers = 128; ++ ab->hw_params.coldboot_cal_mm = false; ++ ab->hw_params.coldboot_cal_ftm = false; ++ } else ++ ath11k_info(ab, "Unsupported FW memory mode: %u\n", fw_mem_mode); ++ } ++ + ath11k_info(ab, "%s\n", ab->hw_params.name); ++ ath11k_info(ab, "FW memory mode: %d\n", ab->hw_params.fw_mem_mode); + + return 0; + } diff --git a/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch b/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch new file mode 100644 index 0000000..59a2165 --- /dev/null +++ b/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch @@ -0,0 +1,332 @@ +From abdd0985a36189ef2cc0e393b027276e86137ace Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 11 Apr 2023 20:08:49 +0200 +Subject: [PATCH] ath11k: remove intersection support for regulatory rules + +Currently, regulatory rules from new country settings is intersected with +rules from default country settings(during initialisation) in order to prevent +users to bypass their default country settings such as power limits, channel +flags, etc. + +However, the country setting in the BDF will take higher higher precendence +and FW will protect it. Therefore, there is no need to handle intersection +on the driver side now. + +Remove regulatory rules intersection logic support. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath11k/reg.c | 168 +++----------------------- + drivers/net/wireless/ath/ath11k/reg.h | 2 +- + drivers/net/wireless/ath/ath11k/wmi.c | 24 +--- + 3 files changed, 16 insertions(+), 178 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -353,134 +353,6 @@ static u32 ath11k_map_fw_phy_flags(u32 p + return flags; + } + +-static bool +-ath11k_reg_can_intersect(struct ieee80211_reg_rule *rule1, +- struct ieee80211_reg_rule *rule2) +-{ +- u32 start_freq1, end_freq1; +- u32 start_freq2, end_freq2; +- +- start_freq1 = rule1->freq_range.start_freq_khz; +- start_freq2 = rule2->freq_range.start_freq_khz; +- +- end_freq1 = rule1->freq_range.end_freq_khz; +- end_freq2 = rule2->freq_range.end_freq_khz; +- +- if ((start_freq1 >= start_freq2 && +- start_freq1 < end_freq2) || +- (start_freq2 > start_freq1 && +- start_freq2 < end_freq1)) +- return true; +- +- /* TODO: Should we restrict intersection feasibility +- * based on min bandwidth of the intersected region also, +- * say the intersected rule should have a min bandwidth +- * of 20MHz? +- */ +- +- return false; +-} +- +-static void ath11k_reg_intersect_rules(struct ieee80211_reg_rule *rule1, +- struct ieee80211_reg_rule *rule2, +- struct ieee80211_reg_rule *new_rule) +-{ +- u32 start_freq1, end_freq1; +- u32 start_freq2, end_freq2; +- u32 freq_diff, max_bw; +- +- start_freq1 = rule1->freq_range.start_freq_khz; +- start_freq2 = rule2->freq_range.start_freq_khz; +- +- end_freq1 = rule1->freq_range.end_freq_khz; +- end_freq2 = rule2->freq_range.end_freq_khz; +- +- new_rule->freq_range.start_freq_khz = max_t(u32, start_freq1, +- start_freq2); +- new_rule->freq_range.end_freq_khz = min_t(u32, end_freq1, end_freq2); +- +- freq_diff = new_rule->freq_range.end_freq_khz - +- new_rule->freq_range.start_freq_khz; +- max_bw = min_t(u32, rule1->freq_range.max_bandwidth_khz, +- rule2->freq_range.max_bandwidth_khz); +- new_rule->freq_range.max_bandwidth_khz = min_t(u32, max_bw, freq_diff); +- +- new_rule->power_rule.max_antenna_gain = +- min_t(u32, rule1->power_rule.max_antenna_gain, +- rule2->power_rule.max_antenna_gain); +- +- new_rule->power_rule.max_eirp = min_t(u32, rule1->power_rule.max_eirp, +- rule2->power_rule.max_eirp); +- +- /* Use the flags of both the rules */ +- new_rule->flags = rule1->flags | rule2->flags; +- +- if ((rule1->flags & NL80211_RRF_PSD) && (rule2->flags & NL80211_RRF_PSD)) +- new_rule->psd = min_t(s8, rule1->psd, rule2->psd); +- else +- new_rule->flags &= ~NL80211_RRF_PSD; +- +- /* To be safe, lts use the max cac timeout of both rules */ +- new_rule->dfs_cac_ms = max_t(u32, rule1->dfs_cac_ms, +- rule2->dfs_cac_ms); +-} +- +-static struct ieee80211_regdomain * +-ath11k_regd_intersect(struct ieee80211_regdomain *default_regd, +- struct ieee80211_regdomain *curr_regd) +-{ +- u8 num_old_regd_rules, num_curr_regd_rules, num_new_regd_rules; +- struct ieee80211_reg_rule *old_rule, *curr_rule, *new_rule; +- struct ieee80211_regdomain *new_regd = NULL; +- u8 i, j, k; +- +- num_old_regd_rules = default_regd->n_reg_rules; +- num_curr_regd_rules = curr_regd->n_reg_rules; +- num_new_regd_rules = 0; +- +- /* Find the number of intersecting rules to allocate new regd memory */ +- for (i = 0; i < num_old_regd_rules; i++) { +- old_rule = default_regd->reg_rules + i; +- for (j = 0; j < num_curr_regd_rules; j++) { +- curr_rule = curr_regd->reg_rules + j; +- +- if (ath11k_reg_can_intersect(old_rule, curr_rule)) +- num_new_regd_rules++; +- } +- } +- +- if (!num_new_regd_rules) +- return NULL; +- +- new_regd = kzalloc(sizeof(*new_regd) + (num_new_regd_rules * +- sizeof(struct ieee80211_reg_rule)), +- GFP_ATOMIC); +- +- if (!new_regd) +- return NULL; +- +- /* We set the new country and dfs region directly and only trim +- * the freq, power, antenna gain by intersecting with the +- * default regdomain. Also MAX of the dfs cac timeout is selected. +- */ +- new_regd->n_reg_rules = num_new_regd_rules; +- memcpy(new_regd->alpha2, curr_regd->alpha2, sizeof(new_regd->alpha2)); +- new_regd->dfs_region = curr_regd->dfs_region; +- new_rule = new_regd->reg_rules; +- +- for (i = 0, k = 0; i < num_old_regd_rules; i++) { +- old_rule = default_regd->reg_rules + i; +- for (j = 0; j < num_curr_regd_rules; j++) { +- curr_rule = curr_regd->reg_rules + j; +- +- if (ath11k_reg_can_intersect(old_rule, curr_rule)) +- ath11k_reg_intersect_rules(old_rule, curr_rule, +- (new_rule + k++)); +- } +- } +- return new_regd; +-} +- + static const char * + ath11k_reg_get_regdom_str(enum nl80211_dfs_regions dfs_region) + { +@@ -631,11 +503,11 @@ ath11k_reg_ap_pwr_convert(enum ieee80211 + + struct ieee80211_regdomain * + ath11k_reg_build_regd(struct ath11k_base *ab, +- struct cur_regulatory_info *reg_info, bool intersect, ++ struct cur_regulatory_info *reg_info, + enum wmi_vdev_type vdev_type, + enum ieee80211_ap_reg_power power_type) + { +- struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL; ++ struct ieee80211_regdomain *new_regd = NULL; + struct cur_reg_rule *reg_rule, *reg_rule_6ghz; + u8 i = 0, j = 0, k = 0; + u8 num_rules; +@@ -678,26 +550,26 @@ ath11k_reg_build_regd(struct ath11k_base + } + + if (!num_rules) +- goto ret; ++ return new_regd; + + /* Add max additional rules to accommodate weather radar band */ + if (reg_info->dfs_region == ATH11K_DFS_REG_ETSI) + num_rules += 2; + +- tmp_regd = kzalloc(sizeof(*tmp_regd) + ++ new_regd = kzalloc(sizeof(*new_regd) + + (num_rules * sizeof(struct ieee80211_reg_rule)), + GFP_ATOMIC); +- if (!tmp_regd) +- goto ret; ++ if (!new_regd) ++ return new_regd; + +- memcpy(tmp_regd->alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1); ++ memcpy(new_regd->alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1); + memcpy(alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1); + alpha2[2] = '\0'; +- tmp_regd->dfs_region = ath11k_map_fw_dfs_region(reg_info->dfs_region); ++ new_regd->dfs_region = ath11k_map_fw_dfs_region(reg_info->dfs_region); + + ath11k_dbg(ab, ATH11K_DBG_REG, + "Country %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n", +- alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region), ++ alpha2, ath11k_reg_get_regdom_str(new_regd->dfs_region), + reg_info->dfs_region, num_rules); + /* Update reg_rules[] below. Firmware is expected to + * send these rules in order(2 GHz rules first and then 5 GHz) +@@ -736,7 +608,7 @@ ath11k_reg_build_regd(struct ath11k_base + flags |= ath11k_map_fw_reg_flags(reg_rule->flags); + flags |= ath11k_map_fw_phy_flags(reg_info->phybitmap); + +- ath11k_reg_update_rule(tmp_regd->reg_rules + i, ++ ath11k_reg_update_rule(new_regd->reg_rules + i, + reg_rule->start_freq, + reg_rule->end_freq, max_bw, + reg_rule->ant_gain, reg_rule->reg_power, +@@ -751,7 +623,7 @@ ath11k_reg_build_regd(struct ath11k_base + reg_info->dfs_region == ATH11K_DFS_REG_ETSI && + (reg_rule->end_freq > ETSI_WEATHER_RADAR_BAND_LOW && + reg_rule->start_freq < ETSI_WEATHER_RADAR_BAND_HIGH)){ +- ath11k_reg_update_weather_radar_band(ab, tmp_regd, ++ ath11k_reg_update_weather_radar_band(ab, new_regd, + reg_rule, &i, + flags, max_bw); + continue; +@@ -762,37 +634,20 @@ ath11k_reg_build_regd(struct ath11k_base + "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n", + i + 1, reg_rule->start_freq, reg_rule->end_freq, + max_bw, reg_rule->ant_gain, reg_rule->reg_power, +- tmp_regd->reg_rules[i].dfs_cac_ms, flags, ++ new_regd->reg_rules[i].dfs_cac_ms, flags, + reg_rule->psd_flag, reg_rule->psd_eirp); + } else { + ath11k_dbg(ab, ATH11K_DBG_REG, + "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", + i + 1, reg_rule->start_freq, reg_rule->end_freq, + max_bw, reg_rule->ant_gain, reg_rule->reg_power, +- tmp_regd->reg_rules[i].dfs_cac_ms, ++ new_regd->reg_rules[i].dfs_cac_ms, + flags); + } + } + +- tmp_regd->n_reg_rules = i; ++ new_regd->n_reg_rules = i; + +- if (intersect) { +- default_regd = ab->default_regd[reg_info->phy_id]; +- +- /* Get a new regd by intersecting the received regd with +- * our default regd. +- */ +- new_regd = ath11k_regd_intersect(default_regd, tmp_regd); +- kfree(tmp_regd); +- if (!new_regd) { +- ath11k_warn(ab, "Unable to create intersected regdomain\n"); +- goto ret; +- } +- } else { +- new_regd = tmp_regd; +- } +- +-ret: + return new_regd; + } + +@@ -844,17 +699,6 @@ void ath11k_regd_update_chan_list_work(s + } + } + +-static bool ath11k_reg_is_world_alpha(char *alpha) +-{ +- if (alpha[0] == '0' && alpha[1] == '0') +- return true; +- +- if (alpha[0] == 'n' && alpha[1] == 'a') +- return true; +- +- return false; +-} +- + static enum wmi_vdev_type ath11k_reg_get_ar_vdev_type(struct ath11k *ar) + { + struct ath11k_vif *arvif; +@@ -877,7 +721,6 @@ int ath11k_reg_handle_chan_list(struct a + enum ieee80211_ap_reg_power power_type) + { + struct ieee80211_regdomain *regd; +- bool intersect = false; + int pdev_idx; + struct ath11k *ar; + enum wmi_vdev_type vdev_type; +@@ -929,24 +772,14 @@ int ath11k_reg_handle_chan_list(struct a + (char *)reg_info->alpha2, 2)) + goto retfail; + +- /* Intersect new rules with default regd if a new country setting was +- * requested, i.e a default regd was already set during initialization +- * and the regd coming from this event has a valid country info. +- */ +- if (ab->default_regd[pdev_idx] && +- !ath11k_reg_is_world_alpha((char *) +- ab->default_regd[pdev_idx]->alpha2) && +- !ath11k_reg_is_world_alpha((char *)reg_info->alpha2)) +- intersect = true; +- + ar = ab->pdevs[pdev_idx].ar; + vdev_type = ath11k_reg_get_ar_vdev_type(ar); + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "wmi handle chan list power type %d vdev type %d intersect %d\n", +- power_type, vdev_type, intersect); ++ "wmi handle chan list power type %d vdev type %d\n", ++ power_type, vdev_type); + +- regd = ath11k_reg_build_regd(ab, reg_info, intersect, vdev_type, power_type); ++ regd = ath11k_reg_build_regd(ab, reg_info, vdev_type, power_type); + if (!regd) { + ath11k_warn(ab, "failed to build regd from reg_info\n"); + goto fallback; +--- a/drivers/net/wireless/ath/ath11k/reg.h ++++ b/drivers/net/wireless/ath/ath11k/reg.h +@@ -36,7 +36,7 @@ void ath11k_regd_update_work(struct work + void ath11k_regd_update_chan_list_work(struct work_struct *work); + struct ieee80211_regdomain * + ath11k_reg_build_regd(struct ath11k_base *ab, +- struct cur_regulatory_info *reg_info, bool intersect, ++ struct cur_regulatory_info *reg_info, + enum wmi_vdev_type vdev_type, + enum ieee80211_ap_reg_power power_type); + int ath11k_regd_update(struct ath11k *ar); diff --git a/patches/ath11k/906-wifi-ath11k-disable-coldboot-for-ipq6018.patch b/patches/ath11k/906-wifi-ath11k-disable-coldboot-for-ipq6018.patch new file mode 100644 index 0000000..d98d24a --- /dev/null +++ b/patches/ath11k/906-wifi-ath11k-disable-coldboot-for-ipq6018.patch @@ -0,0 +1,26 @@ +From a3be23672b4a81256d275af31afc6edcce5c5a26 Mon Sep 17 00:00:00 2001 +From: Mantas Pucka +Date: Mon, 22 Jan 2024 11:38:28 +0200 +Subject: [PATCH] wifi: ath11k: disable coldboot for ipq6018 + +Coldboot calibration does not work at the moment and causes failure during +wifi startup. + +Signed-off-by: Mantas Pucka +--- + drivers/net/wireless/ath/ath11k/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -171,8 +171,8 @@ static struct ath11k_hw_params ath11k_hw + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .coldboot_cal_mm = true, +- .coldboot_cal_ftm = true, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, diff --git a/patches/ath11k/907-wifi-ath11k-disable-coldboot-calibration-for-ipq5018.patch b/patches/ath11k/907-wifi-ath11k-disable-coldboot-calibration-for-ipq5018.patch new file mode 100644 index 0000000..ab8e517 --- /dev/null +++ b/patches/ath11k/907-wifi-ath11k-disable-coldboot-calibration-for-ipq5018.patch @@ -0,0 +1,27 @@ +From b2d16b688ce04b67f2033f90f49f4add7ebd3fe8 Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Tue, 10 Jun 2025 14:34:37 +0400 +Subject: [PATCH] wifi: ath11k: disable coldboot calibration for ipq5018 + +Coldboot calibration does not work causes the firmware to crash during +wifi startup. So let's disable coldboot calibration until a solution is +found. + +Signed-off-by: George Moussalem +--- + drivers/net/wireless/ath/ath11k/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -698,8 +698,8 @@ static struct ath11k_hw_params ath11k_hw + .supports_suspend = false, + .hal_params = &ath11k_hw_hal_params_ipq8074, + .single_pdev_only = false, +- .coldboot_cal_mm = true, +- .coldboot_cal_ftm = true, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = true, + .fix_l1ss = true, + .supports_dynamic_smps_6ghz = false, diff --git a/patches/ath11k/910-ath11k-fix-remapped-ce-accessing-issue-on-64bit-OS.patch b/patches/ath11k/910-ath11k-fix-remapped-ce-accessing-issue-on-64bit-OS.patch new file mode 100644 index 0000000..5878fa0 --- /dev/null +++ b/patches/ath11k/910-ath11k-fix-remapped-ce-accessing-issue-on-64bit-OS.patch @@ -0,0 +1,153 @@ +From: Ziyang Huang +Date: Thu, 2 May 2024 00:14:31 +0800 +Subject: [PATCH] wifi: ath11k: fix remapped ce accessing issue on 64bit OS + +On 64bit OS, when ab->mem_ce is lower than or 4G far away from ab->mem, +u32 is not enough to store the offsets, which makes ath11k_ahb_read32() +and ath11k_ahb_write32() access incorrect address and causes Data Abort +Exception. + +Let's use the high bits of offsets to decide where to access, which is +similar as ath11k_pci_get_window_start() done. In the future, we can merge +these functions for unified regs accessing. + +Signed-off-by: Ziyang Huang +--- + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -198,12 +198,18 @@ static const struct ath11k_pci_ops ath11 + + static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset) + { +- return ioread32(ab->mem + offset); ++ if ((offset & ATH11K_REG_TYPE_MASK) == ATH11K_REG_TYPE_CE) ++ return ioread32(ab->mem_ce + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset)); ++ else ++ return ioread32(ab->mem + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset)); + } + + static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value) + { +- iowrite32(value, ab->mem + offset); ++ if ((offset & ATH11K_REG_TYPE_MASK) == ATH11K_REG_TYPE_CE) ++ iowrite32(value, ab->mem_ce + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset)); ++ else ++ iowrite32(value, ab->mem + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset)); + } + + static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab) +@@ -275,9 +281,9 @@ static void ath11k_ahb_ce_irq_enable(str + const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr; + u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr; + +- ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab); +- ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab); +- ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab); ++ ie1_reg_addr = ce_ie_addr->ie1_reg_addr; ++ ie2_reg_addr = ce_ie_addr->ie2_reg_addr; ++ ie3_reg_addr = ce_ie_addr->ie3_reg_addr; + + ce_attr = &ab->hw_params.host_ce_config[ce_id]; + if (ce_attr->src_nentries) +@@ -296,9 +302,9 @@ static void ath11k_ahb_ce_irq_disable(st + const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr; + u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr; + +- ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab); +- ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab); +- ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab); ++ ie1_reg_addr = ce_ie_addr->ie1_reg_addr; ++ ie2_reg_addr = ce_ie_addr->ie2_reg_addr; ++ ie3_reg_addr = ce_ie_addr->ie3_reg_addr; + + ce_attr = &ab->hw_params.host_ce_config[ce_id]; + if (ce_attr->src_nentries) +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -1247,20 +1247,16 @@ static int ath11k_hal_srng_create_config + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP; + + s = &hal->srng_config[HAL_CE_SRC]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB + +- ATH11K_CE_OFFSET(ab); +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP + +- ATH11K_CE_OFFSET(ab); ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB; ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP; + s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab); + s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab); + + s = &hal->srng_config[HAL_CE_DST]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB + +- ATH11K_CE_OFFSET(ab); +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP + +- ATH11K_CE_OFFSET(ab); ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB; ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP; + s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - +@@ -1268,9 +1264,8 @@ static int ath11k_hal_srng_create_config + + s = &hal->srng_config[HAL_CE_DST_STATUS]; + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + +- HAL_CE_DST_STATUS_RING_BASE_LSB + ATH11K_CE_OFFSET(ab); +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP + +- ATH11K_CE_OFFSET(ab); ++ HAL_CE_DST_STATUS_RING_BASE_LSB; ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP; + s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -2268,9 +2268,9 @@ const struct ce_ie_addr ath11k_ce_ie_add + }; + + const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018 = { +- .ie1_reg_addr = CE_HOST_IPQ5018_IE_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, +- .ie2_reg_addr = CE_HOST_IPQ5018_IE_2_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, +- .ie3_reg_addr = CE_HOST_IPQ5018_IE_3_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .ie1_reg_addr = ATH11K_REG_TYPE_CE + CE_HOST_IPQ5018_IE_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .ie2_reg_addr = ATH11K_REG_TYPE_CE + CE_HOST_IPQ5018_IE_2_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .ie3_reg_addr = ATH11K_REG_TYPE_CE + CE_HOST_IPQ5018_IE_3_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, + }; + + const struct ce_remap ath11k_ce_remap_ipq5018 = { +@@ -2801,13 +2801,13 @@ const struct ath11k_hw_regs ipq5018_regs + .hal_reo_status_hp = 0x00003070, + + /* WCSS relative address */ +- .hal_seq_wcss_umac_ce0_src_reg = 0x08400000 ++ .hal_seq_wcss_umac_ce0_src_reg = ATH11K_REG_TYPE_CE + 0x08400000 + - HAL_IPQ5018_CE_WFSS_REG_BASE, +- .hal_seq_wcss_umac_ce0_dst_reg = 0x08401000 ++ .hal_seq_wcss_umac_ce0_dst_reg = ATH11K_REG_TYPE_CE + 0x08401000 + - HAL_IPQ5018_CE_WFSS_REG_BASE, +- .hal_seq_wcss_umac_ce1_src_reg = 0x08402000 ++ .hal_seq_wcss_umac_ce1_src_reg = ATH11K_REG_TYPE_CE + 0x08402000 + - HAL_IPQ5018_CE_WFSS_REG_BASE, +- .hal_seq_wcss_umac_ce1_dst_reg = 0x08403000 ++ .hal_seq_wcss_umac_ce1_dst_reg = ATH11K_REG_TYPE_CE + 0x08403000 + - HAL_IPQ5018_CE_WFSS_REG_BASE, + + /* WBM Idle address */ +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -81,7 +81,12 @@ + #define ATH11K_M3_FILE "m3.bin" + #define ATH11K_REGDB_FILE_NAME "regdb.bin" + +-#define ATH11K_CE_OFFSET(ab) (ab->mem_ce - ab->mem) ++#define ATH11K_REG_TYPE_MASK GENMASK(31, 28) ++#define ATH11K_REG_TYPE(x) FIELD_PREP_CONST(ATH11K_REG_TYPE_MASK, x) ++#define ATH11K_REG_TYPE_NORMAL ATH11K_REG_TYPE(0) ++#define ATH11K_REG_TYPE_DP ATH11K_REG_TYPE(1) ++#define ATH11K_REG_TYPE_CE ATH11K_REG_TYPE(2) ++#define ATH11K_REG_OFFSET_MASK GENMASK(27, 0) + + enum ath11k_hw_rate_cck { + ATH11K_HW_RATE_CCK_LP_11M = 0, diff --git a/patches/ath11k/920-wifi-ath11k-add-hw-params-for-QCN6122.patch b/patches/ath11k/920-wifi-ath11k-add-hw-params-for-QCN6122.patch new file mode 100644 index 0000000..cb173d2 --- /dev/null +++ b/patches/ath11k/920-wifi-ath11k-add-hw-params-for-QCN6122.patch @@ -0,0 +1,120 @@ +From: George Moussalem +Date: Wed, 27 Oct 2024 16:34:11 +0400 +Subject: [PATCH] wifi: ath11k: add hw params for QCN6122 + +Add QCN6122 platform support. + +QCN6122 is a PCIe based solution that is attached to and enumerated +by the WPSS (Wireless Processor SubSystem) Q6 processor. + +Though it is a PCIe device, since it is not attached to APSS processor +(Application Processor SubSystem), APSS will be unaware of such a decice +and hence it is registered to the APSS processor as a platform device(AHB). +Because of this hybrid nature, it is called as a hybrid bus device. + +As such, QCN6122 is a hybrid bus type device and follows the same codepath +as for WCN6750. + +This is a heavily simplified version of below downstream patch: +Download from https://git.codelinaro.org/clo/qsdk/oss/system/feeds/wlan-open/-/blob/NHSS.QSDK.12.4.5.r2/mac80211/patches/232-ath11k-qcn6122-support.patch + +Co-developed-by: George Moussalem +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: George Moussalem +--- + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -905,6 +905,67 @@ static struct ath11k_hw_params ath11k_hw + .support_dual_stations = true, + .pdev_suspend = false, + }, ++ { ++ .hw_rev = ATH11K_HW_QCN6122_HW10, ++ .name = "qcn6122 hw1.0", ++ .fw = { ++ .dir = "QCN6122/hw1.0", ++ .board_size = 256 * 1024, ++ .cal_offset = 128 * 1024, ++ }, ++ .hal_params = &ath11k_hw_hal_params_ipq8074, ++ .max_radios = MAX_RADIOS_5018, ++ .bdf_addr = 0x4D200000, ++ .hw_ops = &ipq5018_ops, ++ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), ++ .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122, ++ .interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), ++ .spectral = { ++ .fft_sz = 2, ++ .fft_pad_sz = 0, ++ .summary_pad_sz = 16, ++ .fft_hdr_len = 24, ++ .max_fft_bins = 1024, ++ }, ++ .credit_flow = false, ++ .max_tx_ring = 1, ++ .supports_monitor = true, ++ .supports_shadow_regs = false, ++ .idle_ps = false, ++ .supports_suspend = false, ++ .host_ce_config = ath11k_host_ce_config_qcn9074, ++ .ce_count = CE_CNT_5018, ++ .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, ++ .target_ce_count = TARGET_CE_CNT_5018, ++ .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018, ++ .svc_to_ce_map_len = SVC_CE_MAP_LEN_5018, ++ .single_pdev_only = false, ++ .rxdma1_enable = true, ++ .num_rxdma_per_pdev = RXDMA_PER_PDEV_5018, ++ .rx_mac_buf_ring = false, ++ .vdev_start_delay = false, ++ .htt_peer_map_v2 = true, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, ++ .cbcal_restart_fw = true, ++ .fix_l1ss = true, ++ .alloc_cacheable_memory = true, ++ .m3_fw_support = false, ++ .fixed_bdf_addr = true, ++ .fixed_mem_region = true, ++ .static_window_map = true, ++ .hybrid_bus_type = true, ++ .fw_mem_mode = 1, ++ .supports_sta_ps = false, ++ .dbr_debug_support = true, ++ .bios_sar_capa = NULL, ++ .fixed_fw_mem = false, ++ .support_off_channel_tx = false, ++ .tcl_ring_retry = true, ++ .tx_ring_size = DP_TCL_DATA_RING_SIZE, ++ }, + }; + + static const struct dmi_system_id ath11k_pm_quirk_table[] = { +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -151,6 +151,7 @@ enum ath11k_hw_rev { + ATH11K_HW_IPQ5018_HW10, + ATH11K_HW_QCA2066_HW21, + ATH11K_HW_QCA6698AQ_HW21, ++ ATH11K_HW_QCN6122_HW10, + }; + + enum ath11k_firmware_mode { +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -22,10 +22,11 @@ + #define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074 0x02 + #define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074 0x07 + #define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_WCN6750 0x03 ++#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122 0x40 + #define ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 32 + #define ATH11K_QMI_RESP_LEN_MAX 8192 + #define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 52 +-#define ATH11K_QMI_CALDB_SIZE 0x480000 ++#define ATH11K_QMI_CALDB_SIZE 0x500000 + #define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20 + #define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 5 + diff --git a/patches/ath11k/921-wifi-ath11k-add-hal-regs-for-QCN6122.patch b/patches/ath11k/921-wifi-ath11k-add-hal-regs-for-QCN6122.patch new file mode 100644 index 0000000..4ecf1d3 --- /dev/null +++ b/patches/ath11k/921-wifi-ath11k-add-hal-regs-for-QCN6122.patch @@ -0,0 +1,114 @@ +From: George Moussalem +Date: Wed, 27 Oct 2024 16:34:11 +0400 +Subject: [PATCH] wifi: ath11k: add hal regs for QCN6122 + +Add HAL changes required to support QCN6122. Offsets are similar to those of +WCN6750 but QCN6122 does not use the hal_shadow_base_addr, so add platform +specific ath11k_hw_regs and register them in hw params. + +Signed-off-by: George Moussalem +--- +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -918,6 +918,7 @@ static struct ath11k_hw_params ath11k_hw + .bdf_addr = 0x4D200000, + .hw_ops = &ipq5018_ops, + .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), ++ .regs = &qcn6122_regs, + .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122, + .interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -2822,6 +2822,81 @@ const struct ath11k_hw_regs ipq5018_regs + .hal_wbm1_release_ring_base_lsb = 0x0000097c, + }; + ++const struct ath11k_hw_regs qcn6122_regs = { ++ /* SW2TCL(x) R0 ring configuration address */ ++ .hal_tcl1_ring_base_lsb = 0x00000694, ++ .hal_tcl1_ring_base_msb = 0x00000698, ++ .hal_tcl1_ring_id = 0x0000069c, ++ .hal_tcl1_ring_misc = 0x000006a4, ++ .hal_tcl1_ring_tp_addr_lsb = 0x000006b0, ++ .hal_tcl1_ring_tp_addr_msb = 0x000006b4, ++ .hal_tcl1_ring_consumer_int_setup_ix0 = 0x000006c4, ++ .hal_tcl1_ring_consumer_int_setup_ix1 = 0x000006c8, ++ .hal_tcl1_ring_msi1_base_lsb = 0x000006dc, ++ .hal_tcl1_ring_msi1_base_msb = 0x000006e0, ++ .hal_tcl1_ring_msi1_data = 0x000006e4, ++ .hal_tcl2_ring_base_lsb = 0x000006ec, ++ .hal_tcl_ring_base_lsb = 0x0000079c, ++ ++ /* TCL STATUS ring address */ ++ .hal_tcl_status_ring_base_lsb = 0x000008a4, ++ ++ /* REO2SW(x) R0 ring configuration address */ ++ .hal_reo1_ring_base_lsb = 0x000001ec, ++ .hal_reo1_ring_base_msb = 0x000001f0, ++ .hal_reo1_ring_id = 0x000001f4, ++ .hal_reo1_ring_misc = 0x000001fc, ++ .hal_reo1_ring_hp_addr_lsb = 0x00000200, ++ .hal_reo1_ring_hp_addr_msb = 0x00000204, ++ .hal_reo1_ring_producer_int_setup = 0x00000210, ++ .hal_reo1_ring_msi1_base_lsb = 0x00000234, ++ .hal_reo1_ring_msi1_base_msb = 0x00000238, ++ .hal_reo1_ring_msi1_data = 0x0000023c, ++ .hal_reo2_ring_base_lsb = 0x00000244, ++ .hal_reo1_aging_thresh_ix_0 = 0x00000564, ++ .hal_reo1_aging_thresh_ix_1 = 0x00000568, ++ .hal_reo1_aging_thresh_ix_2 = 0x0000056c, ++ .hal_reo1_aging_thresh_ix_3 = 0x00000570, ++ ++ /* REO2SW(x) R2 ring pointers (head/tail) address */ ++ .hal_reo1_ring_hp = 0x00003028, ++ .hal_reo1_ring_tp = 0x0000302c, ++ .hal_reo2_ring_hp = 0x00003030, ++ ++ /* REO2TCL R0 ring configuration address */ ++ .hal_reo_tcl_ring_base_lsb = 0x000003fc, ++ .hal_reo_tcl_ring_hp = 0x00003058, ++ ++ /* SW2REO ring address */ ++ .hal_sw2reo_ring_base_lsb = 0x0000013c, ++ .hal_sw2reo_ring_hp = 0x00003018, ++ ++ /* REO CMD ring address */ ++ .hal_reo_cmd_ring_base_lsb = 0x000000e4, ++ .hal_reo_cmd_ring_hp = 0x00003010, ++ ++ /* REO status address */ ++ .hal_reo_status_ring_base_lsb = 0x00000504, ++ .hal_reo_status_hp = 0x00003070, ++ ++ /* WCSS relative address */ ++ .hal_seq_wcss_umac_ce0_src_reg = 0x01b80000, ++ .hal_seq_wcss_umac_ce0_dst_reg = 0x01b81000, ++ .hal_seq_wcss_umac_ce1_src_reg = 0x01b82000, ++ .hal_seq_wcss_umac_ce1_dst_reg = 0x01b83000, ++ ++ /* WBM Idle address */ ++ .hal_wbm_idle_link_ring_base_lsb = 0x00000874, ++ .hal_wbm_idle_link_ring_misc = 0x00000884, ++ ++ /* SW2WBM release address */ ++ .hal_wbm_release_ring_base_lsb = 0x000001ec, ++ ++ /* WBM2SW release address */ ++ .hal_wbm0_release_ring_base_lsb = 0x00000924, ++ .hal_wbm1_release_ring_base_lsb = 0x0000097c, ++}; ++ + const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = { + .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, + .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074, +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -426,6 +426,7 @@ extern const struct ath11k_hw_regs qcn90 + extern const struct ath11k_hw_regs wcn6855_regs; + extern const struct ath11k_hw_regs wcn6750_regs; + extern const struct ath11k_hw_regs ipq5018_regs; ++extern const struct ath11k_hw_regs qcn6122_regs; + + static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type) + { diff --git a/patches/ath11k/922-wifi-ath11k-add-hw-ring-mask-for-QCN6122.patch b/patches/ath11k/922-wifi-ath11k-add-hw-ring-mask-for-QCN6122.patch new file mode 100644 index 0000000..b54461f --- /dev/null +++ b/patches/ath11k/922-wifi-ath11k-add-hw-ring-mask-for-QCN6122.patch @@ -0,0 +1,74 @@ +From: George Moussalem +Date: Wed, 27 Oct 2024 16:34:11 +0400 +Subject: [PATCH] wifi: ath11k: add hw ring mask for QCN6122 + +Add ring mask for QCN6122 and register them in hw params. + +Signed-off-by: George Moussalem +--- +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -917,6 +917,7 @@ static struct ath11k_hw_params ath11k_hw + .max_radios = MAX_RADIOS_5018, + .bdf_addr = 0x4D200000, + .hw_ops = &ipq5018_ops, ++ .ring_mask = &ath11k_hw_ring_mask_qcn6122, + .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), + .regs = &qcn6122_regs, + .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122, +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -2070,6 +2070,43 @@ const struct ath11k_hw_ring_mask ath11k_ + }, + }; + ++const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn6122 = { ++ .tx = { ++ ATH11K_TX_RING_MASK_0, ++ ATH11K_TX_RING_MASK_1, ++ ATH11K_TX_RING_MASK_2, ++ }, ++ .rx_mon_status = { ++ 0, 0, 0, ++ ATH11K_RX_MON_STATUS_RING_MASK_0, ++ }, ++ .rx = { ++ 0, 0, 0, 0, ++ ATH11K_RX_RING_MASK_0, ++ ATH11K_RX_RING_MASK_1, ++ ATH11K_RX_RING_MASK_2, ++ ATH11K_RX_RING_MASK_3, ++ }, ++ .rx_err = { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ ATH11K_RX_ERR_RING_MASK_0, ++ }, ++ .rx_wbm_rel = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ ATH11K_RX_WBM_REL_RING_MASK_0, ++ }, ++ .reo_status = { ++ 0, 0, 0, ++ ATH11K_REO_STATUS_RING_MASK_0, ++ }, ++ .rxdma2host = { ++ ATH11K_RXDMA2HOST_RING_MASK_0, ++ }, ++ .host2rxdma = { ++ ATH11K_HOST2RXDMA_RING_MASK_0, ++ }, ++}; ++ + /* Target firmware's Copy Engine configuration for IPQ5018 */ + const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[] = { + /* CE0: host->target HTC control and raw streams */ +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -290,6 +290,7 @@ extern const struct ath11k_hw_ring_mask + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390; + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074; + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_wcn6750; ++extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn6122; + + extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq8074; + extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018; diff --git a/patches/ath11k/923-wifi-ath11k-update-hif_and-pci_ops-for-QCN6122.patch b/patches/ath11k/923-wifi-ath11k-update-hif_and-pci_ops-for-QCN6122.patch new file mode 100644 index 0000000..fd4922b --- /dev/null +++ b/patches/ath11k/923-wifi-ath11k-update-hif_and-pci_ops-for-QCN6122.patch @@ -0,0 +1,102 @@ +From: George Moussalem +Date: Wed, 27 Oct 2024 16:34:11 +0400 +Subject: [PATCH] wifi: ath11k: update hif and pci ops for QCN6122 + +Add HIF and PCI ops for QCN6122. QCN6122 by default uses DP window 3. +However, this is configurable, so let's introduce a function to do that and +follow the existing register access code for (hybrid)AHB devices and use +DP window 1. + +Signed-off-by: George Moussalem +--- +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -768,6 +768,18 @@ static int ath11k_ahb_hif_resume(struct + return 0; + } + ++static void ath11k_ahb_config_static_window_qcn6122(struct ath11k_base *ab) ++{ ++ u32 umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET); ++ u32 ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE); ++ u32 window; ++ ++ window = (umac_window) | (ce_window << 6); ++ ++ iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window, ++ ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS); ++} ++ + static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = { + .start = ath11k_ahb_start, + .stop = ath11k_ahb_stop, +@@ -800,6 +812,24 @@ static const struct ath11k_hif_ops ath11 + .ce_irq_disable = ath11k_pci_disable_ce_irqs_except_wake_irq, + }; + ++static const struct ath11k_hif_ops ath11k_ahb_hif_ops_qcn6122 = { ++ .start = ath11k_pcic_start, ++ .stop = ath11k_pcic_stop, ++ .read32 = ath11k_pcic_read32, ++ .write32 = ath11k_pcic_write32, ++ .read = NULL, ++ .irq_enable = ath11k_pcic_ext_irq_enable, ++ .irq_disable = ath11k_pcic_ext_irq_disable, ++ .get_msi_address = ath11k_pcic_get_msi_address, ++ .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment, ++ .map_service_to_pipe = ath11k_pcic_map_service_to_pipe, ++ .power_down = ath11k_ahb_power_down, ++ .power_up = ath11k_ahb_power_up, ++ .ce_irq_enable = ath11k_pci_enable_ce_irqs_except_wake_irq, ++ .ce_irq_disable = ath11k_pci_disable_ce_irqs_except_wake_irq, ++ .config_static_window = ath11k_ahb_config_static_window_qcn6122, ++}; ++ + static int ath11k_core_get_rproc(struct ath11k_base *ab) + { + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); +@@ -1144,6 +1174,10 @@ static int ath11k_ahb_probe(struct platf + hif_ops = &ath11k_ahb_hif_ops_wcn6750; + pci_ops = &ath11k_ahb_pci_ops_wcn6750; + break; ++ case ATH11K_HW_QCN6122_HW10: ++ hif_ops = &ath11k_ahb_hif_ops_qcn6122; ++ pci_ops = &ath11k_ahb_pci_ops_wcn6750; ++ break; + default: + dev_err(&pdev->dev, "unsupported device type %d\n", hw_rev); + return -EOPNOTSUPP; +--- a/drivers/net/wireless/ath/ath11k/hif.h ++++ b/drivers/net/wireless/ath/ath11k/hif.h +@@ -32,6 +32,7 @@ struct ath11k_hif_ops { + void (*ce_irq_disable)(struct ath11k_base *ab); + void (*get_ce_msi_idx)(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx); + void (*coredump_download)(struct ath11k_base *ab); ++ void (*config_static_window)(struct ath11k_base *ab); + }; + + static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab) +@@ -159,4 +160,12 @@ static inline void ath11k_hif_coredump_d + ab->hif.ops->coredump_download(ab); + } + ++static inline void ath11k_hif_config_static_window(struct ath11k_base *ab) ++{ ++ if (!ab->hw_params.static_window_map || !ab->hif.ops->config_static_window) ++ return; ++ ++ ab->hif.ops->config_static_window(ab); ++} ++ + #endif /* _HIF_H_ */ +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2201,6 +2201,8 @@ static int ath11k_qmi_request_device_inf + if (!ab->hw_params.ce_remap) + ab->mem_ce = ab->mem; + ++ ath11k_hif_config_static_window(ab); ++ + return 0; + out: + return ret; diff --git a/patches/ath11k/924-wifi-ath11k-add-multipd-support-for-QCN6122.patch b/patches/ath11k/924-wifi-ath11k-add-multipd-support-for-QCN6122.patch new file mode 100644 index 0000000..e67e4a7 --- /dev/null +++ b/patches/ath11k/924-wifi-ath11k-add-multipd-support-for-QCN6122.patch @@ -0,0 +1,110 @@ +From: George Moussalem +Date: Wed, 27 Oct 2024 16:34:11 +0400 +Subject: [PATCH] wifi: ath11k: add multipd support for QCN6122 + +IPQ5018/QCN6122 platforms use multi PD (protection domains) to avoid having +one instance of the running Q6 firmware crashing resulting in crashing the +others. See below patch for more info: +https://lore.kernel.org/all/20231110091939.3025413-1-quic_mmanikan@quicinc.com/ + +The IPQ5018 platform can have multiple (2) QCN6122 wifi cards. To differentiate +the two, the PD instance number (1 or 2) is added to the QMI service instance +ID, which the QCN6122 firmware also expects. IPQ5018 is always the first PD, so +the QCN6122 cards should be the second or third. + +Signed-off-by: George Moussalem +--- +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -435,6 +435,7 @@ static void ath11k_ahb_init_qmi_ce_confi + cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len; + cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map; + ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; ++ ab->qmi.service_ins_id += ab->userpd_id; + } + + static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) +@@ -1118,6 +1119,27 @@ err_unregister: + return ret; + } + ++static int ath11k_get_userpd_id(struct device *dev) ++{ ++ int ret; ++ int userpd_id = 0; ++ const char *subsys_name; ++ ++ ret = of_property_read_string(dev->of_node, ++ "qcom,userpd-subsys-name", ++ &subsys_name); ++ if (ret) ++ return 0; ++ ++ if (strcmp(subsys_name, "q6v5_wcss_userpd2") == 0) ++ userpd_id = ATH11K_QCN6122_USERPD_2; ++ else if (strcmp(subsys_name, "q6v5_wcss_userpd3") == 0) ++ userpd_id = ATH11K_QCN6122_USERPD_3; ++ dev_info(dev, "Multipd architecture - userpd: %d\n", userpd_id + 1); ++ ++ return userpd_id; ++} ++ + static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab) + { + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); +@@ -1159,7 +1181,7 @@ static int ath11k_ahb_probe(struct platf + const struct ath11k_hif_ops *hif_ops; + const struct ath11k_pci_ops *pci_ops; + enum ath11k_hw_rev hw_rev; +- int ret; ++ int ret, userpd_id; + + hw_rev = (uintptr_t)device_get_match_data(&pdev->dev); + +@@ -1183,6 +1205,7 @@ static int ath11k_ahb_probe(struct platf + return -EOPNOTSUPP; + } + ++ userpd_id = ath11k_get_userpd_id(&pdev->dev); + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n"); +@@ -1199,6 +1222,7 @@ static int ath11k_ahb_probe(struct platf + ab->hif.ops = hif_ops; + ab->pdev = pdev; + ab->hw_rev = hw_rev; ++ ab->userpd_id = userpd_id; + ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; + platform_set_drvdata(pdev, ab); + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -47,6 +47,9 @@ + #define ATH11K_INVALID_HW_MAC_ID 0xFF + #define ATH11K_CONNECTION_LOSS_HZ (3 * HZ) + ++#define ATH11K_QCN6122_USERPD_2 1 ++#define ATH11K_QCN6122_USERPD_3 2 ++ + /* SMBIOS type containing Board Data File Name Extension */ + #define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8 + +@@ -966,6 +969,7 @@ struct ath11k_base { + struct list_head peers; + wait_queue_head_t peer_mapping_wq; + u8 mac_addr[ETH_ALEN]; ++ int userpd_id; + int irq_num[ATH11K_IRQ_NUM_MAX]; + struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX]; + struct ath11k_targ_cap target_caps; +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -391,6 +391,8 @@ static void ath11k_pci_init_qmi_ce_confi + } else + ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; + ++ ab->qmi.service_ins_id += ab->userpd_id; ++ + ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2, + &cfg->shadow_reg_v2_len); + } diff --git a/patches/ath11k/925-wifi-ath11k-add-QCN6122-device-support.patch b/patches/ath11k/925-wifi-ath11k-add-QCN6122-device-support.patch new file mode 100644 index 0000000..b8b12dd --- /dev/null +++ b/patches/ath11k/925-wifi-ath11k-add-QCN6122-device-support.patch @@ -0,0 +1,55 @@ +From: George Moussalem +Date: Wed, 27 Oct 2024 16:34:11 +0400 +Subject: [PATCH] wifi: ath11k: add QCN6122 device support + +QCN6122 is a 2x2 11AX PCIe based chipset, but it is attached to the WPSS +(Wireless Processor SubSystem) Q6 processor, hence it is enumerated +by the Q6 processor. It is registered to the APSS processor +(Application Processor SubSystem) as a platform device (AHB) and remoteproc +APIs are used to boot up or shutdown the device like other AHB devices. + +Also, device information like BAR and its size is not known to the +APSS processor as the chip is enumerated by WPSS Q6. These details +are fetched over QMI. + +STA, AP, and MESH modes are supported. +Tested on: Linksys MX2000 and GLiNET B3000 access points for prolonged duration +tests spanning multiple days with multiple clients connected with firmware +WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +An important point to note is that though QCN6122 is a PCIe device, +it is an IPQ5018 SoC specific solution and cannot be attached to any other +platform. + +Signed-off-by: George Moussalem +--- +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -37,6 +37,9 @@ static const struct of_device_id ath11k_ + { .compatible = "qcom,ipq5018-wifi", + .data = (void *)ATH11K_HW_IPQ5018_HW10, + }, ++ { .compatible = "qcom,qcn6122-wifi", ++ .data = (void *)ATH11K_HW_QCN6122_HW10, ++ }, + { } + }; + +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -137,6 +137,15 @@ static const struct ath11k_msi_config at + }, + .hw_rev = ATH11K_HW_QCA6698AQ_HW21, + }, ++ { ++ .total_vectors = 13, ++ .total_users = 2, ++ .users = (struct ath11k_msi_user[]) { ++ { .name = "CE", .num_vectors = 5, .base_vector = 0 }, ++ { .name = "DP", .num_vectors = 8, .base_vector = 5 }, ++ }, ++ .hw_rev = ATH11K_HW_QCN6122_HW10, ++ }, + }; + + int ath11k_pcic_init_msi_config(struct ath11k_base *ab) diff --git a/patches/ath11k/931-wifi-ath11k-Support-to-assign-m3-dump-memory.patch b/patches/ath11k/931-wifi-ath11k-Support-to-assign-m3-dump-memory.patch new file mode 100644 index 0000000..6888b9a --- /dev/null +++ b/patches/ath11k/931-wifi-ath11k-Support-to-assign-m3-dump-memory.patch @@ -0,0 +1,31 @@ +From 64f6f6cdde0b6b763181145a698207fad4536c06 Mon Sep 17 00:00:00 2001 +From: Ziyang Huang +Date: Wed, 9 Aug 2023 17:44:49 +0000 +Subject: [PATCH] wifi: ath11k: Support to assign m3 dump memory + +Signed-off-by: Ziyang Huang +--- + drivers/net/wireless/ath/ath11k/qmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2118,6 +2118,18 @@ static int ath11k_qmi_assign_target_mem_ + ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; + idx++; + break; ++ case M3_DUMP_REGION_TYPE: ++ if (of_property_read_u32(dev->of_node, "qcom,m3-dump-addr", &addr)) { ++ ath11k_warn(ab, "qmi fail to get qcom,m3-dump-addr, ignore m3 dump mem req\n"); ++ break; ++ } ++ ++ ab->qmi.target_mem[idx].paddr = (phys_addr_t) addr; ++ ab->qmi.target_mem[idx].vaddr = NULL; ++ ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; ++ ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; ++ idx++; ++ break; + default: + ath11k_warn(ab, "qmi ignore invalid mem req type %d\n", + ab->qmi.target_mem[i].type); diff --git a/patches/ath11k/932-wifi-ath11k-poll-reo-status-ipq5018.patch b/patches/ath11k/932-wifi-ath11k-poll-reo-status-ipq5018.patch new file mode 100644 index 0000000..8943466 --- /dev/null +++ b/patches/ath11k/932-wifi-ath11k-poll-reo-status-ipq5018.patch @@ -0,0 +1,164 @@ +From d890c6d602307c9297df12c7d0287f9ffd26208b Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 12 May 2021 19:21:09 +0530 +Subject: [PATCH] ath11k: poll reo status ring for IPQ5018 + +Currently reo status interrupts are not received +due to wrong mapping of the reo status interrupt +line in IPQ5018. + +Hence, until the mapping is resolved in HW, use +polling to reap the reo status ring. Rather than +a period timer to reap the ring, the timer is +triggered only on sending a reo command with +status request. + +Without proper reaping of the ring, backpressure +and ring full issues are seen in multi client test +setups which leads to flooding the console with +error messages reporting failure to send reo cmds. + +Can be reverted once HW solution is available. + +Signed-off-by: Sriram R +--- +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -727,6 +727,7 @@ static struct ath11k_hw_params ath11k_hw + .support_fw_mac_sequence = false, + .support_dual_stations = false, + .pdev_suspend = false, ++ .reo_status_poll = true, + }, + { + .name = "qca2066 hw2.1", +--- a/drivers/net/wireless/ath/ath11k/dp.c ++++ b/drivers/net/wireless/ath/ath11k/dp.c +@@ -348,12 +348,66 @@ void ath11k_dp_stop_shadow_timers(struct + ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer); + } + ++static void ath11k_dp_handle_reo_status_timer(struct timer_list *timer) ++{ ++ struct ath11k_dp *dp = from_timer(dp, timer, reo_status_timer); ++ struct ath11k_base *ab = dp->ab; ++ ++ spin_lock_bh(&dp->reo_cmd_lock); ++ dp->reo_status_timer_running = false; ++ spin_unlock_bh(&dp->reo_cmd_lock); ++ ++ ath11k_dp_process_reo_status(ab); ++} ++ ++void ath11k_dp_start_reo_status_timer(struct ath11k_base *ab) ++{ ++ struct ath11k_dp *dp = &ab->dp; ++ ++ if (!ab->hw_params.reo_status_poll) ++ return; ++ ++ spin_lock_bh(&dp->reo_cmd_lock); ++ if (dp->reo_status_timer_running) { ++ spin_unlock_bh(&dp->reo_cmd_lock); ++ return; ++ } ++ dp->reo_status_timer_running = true; ++ spin_unlock_bh(&dp->reo_cmd_lock); ++ ++ mod_timer(&dp->reo_status_timer, jiffies + ++ msecs_to_jiffies(ATH11K_REO_STATUS_POLL_TIMEOUT_MS)); ++} ++ ++static void ath11k_dp_stop_reo_status_timer(struct ath11k_base *ab) ++{ ++ struct ath11k_dp *dp = &ab->dp; ++ ++ if (!ab->hw_params.reo_status_poll) ++ return; ++ ++ del_timer_sync(&dp->reo_status_timer); ++ dp->reo_status_timer_running = false; ++} ++ ++static void ath11k_dp_init_reo_status_timer(struct ath11k_base *ab) ++{ ++ struct ath11k_dp *dp = &ab->dp; ++ ++ if (!ab->hw_params.reo_status_poll) ++ return; ++ ++ timer_setup(&dp->reo_status_timer, ++ ath11k_dp_handle_reo_status_timer, 0); ++} ++ + static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab) + { + struct ath11k_dp *dp = &ab->dp; + int i; + + ath11k_dp_stop_shadow_timers(ab); ++ ath11k_dp_stop_reo_status_timer(ab); + ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring); + ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring); + ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring); +@@ -375,6 +429,8 @@ static int ath11k_dp_srng_common_setup(s + int i, ret; + u8 tcl_num, wbm_num; + ++ ath11k_dp_init_reo_status_timer(ab); ++ + ret = ath11k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring, + HAL_SW2WBM_RELEASE, 0, 0, + DP_WBM_RELEASE_RING_SIZE); +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -46,6 +46,8 @@ struct dp_rx_tid { + #define DP_MON_PURGE_TIMEOUT_MS 100 + #define DP_MON_SERVICE_BUDGET 128 + ++#define ATH11K_REO_STATUS_POLL_TIMEOUT_MS 10 ++ + struct dp_reo_cache_flush_elem { + struct list_head list; + struct dp_rx_tid data; +@@ -287,6 +289,10 @@ struct ath11k_dp { + spinlock_t reo_cmd_lock; + struct ath11k_hp_update_timer reo_cmd_timer; + struct ath11k_hp_update_timer tx_ring_timer[DP_TCL_NUM_RING_MAX]; ++ ++ /* reo status timer and flags */ ++ struct timer_list reo_status_timer; ++ bool reo_status_timer_running; + }; + + /* HTT definitions */ +@@ -1690,5 +1696,6 @@ void ath11k_dp_shadow_init_timer(struct + struct ath11k_hp_update_timer *update_timer, + u32 interval, u32 ring_id); + void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab); ++void ath11k_dp_start_reo_status_timer(struct ath11k_base *ab); + + #endif +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -787,6 +787,10 @@ int ath11k_dp_tx_send_reo_cmd(struct ath + if (cmd_num == 0) + return -EINVAL; + ++ /* Trigger reo status polling if required */ ++ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) ++ ath11k_dp_start_reo_status_timer(ab); ++ + if (!cb) + return 0; + +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -233,6 +233,7 @@ struct ath11k_hw_params { + bool support_fw_mac_sequence; + bool support_dual_stations; + bool pdev_suspend; ++ bool reo_status_poll; + }; + + struct ath11k_hw_ops { diff --git a/patches/ath11k/940-ath11k-clear_initialized_flag_for_deinit-ed_srng_lists.patch b/patches/ath11k/940-ath11k-clear_initialized_flag_for_deinit-ed_srng_lists.patch new file mode 100644 index 0000000..e092e9d --- /dev/null +++ b/patches/ath11k/940-ath11k-clear_initialized_flag_for_deinit-ed_srng_lists.patch @@ -0,0 +1,92 @@ +From 16872194c80f2724472fc207991712895ac8a230 Mon Sep 17 00:00:00 2001 +From: Sergey Senozhatsky +Date: Thu, 12 Jun 2025 17:45:06 +0900 +Subject: wifi: ath11k: clear initialized flag for deinit-ed srng lists + +[ Upstream commit a5b46aa7cf5f05c213316a018e49a8e086efd98e ] + +In a number of cases we see kernel panics on resume due +to ath11k kernel page fault, which happens under the +following circumstances: + +1) First ath11k_hal_dump_srng_stats() call + + Last interrupt received for each group: + ath11k_pci 0000:01:00.0: group_id 0 22511ms before + ath11k_pci 0000:01:00.0: group_id 1 14440788ms before + [..] + ath11k_pci 0000:01:00.0: failed to receive control response completion, polling.. + ath11k_pci 0000:01:00.0: Service connect timeout + ath11k_pci 0000:01:00.0: failed to connect to HTT: -110 + ath11k_pci 0000:01:00.0: failed to start core: -110 + ath11k_pci 0000:01:00.0: firmware crashed: MHI_CB_EE_RDDM + ath11k_pci 0000:01:00.0: already resetting count 2 + ath11k_pci 0000:01:00.0: failed to wait wlan mode request (mode 4): -110 + ath11k_pci 0000:01:00.0: qmi failed to send wlan mode off: -110 + ath11k_pci 0000:01:00.0: failed to reconfigure driver on crash recovery + [..] + +2) At this point reconfiguration fails (we have 2 resets) and + ath11k_core_reconfigure_on_crash() calls ath11k_hal_srng_deinit() + which destroys srng lists. However, it does not reset per-list + ->initialized flag. + +3) Second ath11k_hal_dump_srng_stats() call sees stale ->initialized + flag and attempts to dump srng stats: + + Last interrupt received for each group: + ath11k_pci 0000:01:00.0: group_id 0 66785ms before + ath11k_pci 0000:01:00.0: group_id 1 14485062ms before + ath11k_pci 0000:01:00.0: group_id 2 14485062ms before + ath11k_pci 0000:01:00.0: group_id 3 14485062ms before + ath11k_pci 0000:01:00.0: group_id 4 14780845ms before + ath11k_pci 0000:01:00.0: group_id 5 14780845ms before + ath11k_pci 0000:01:00.0: group_id 6 14485062ms before + ath11k_pci 0000:01:00.0: group_id 7 66814ms before + ath11k_pci 0000:01:00.0: group_id 8 68997ms before + ath11k_pci 0000:01:00.0: group_id 9 67588ms before + ath11k_pci 0000:01:00.0: group_id 10 69511ms before + BUG: unable to handle page fault for address: ffffa007404eb010 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 100000067 P4D 100000067 PUD 10022d067 PMD 100b01067 PTE 0 + Oops: 0000 [#1] PREEMPT SMP NOPTI + RIP: 0010:ath11k_hal_dump_srng_stats+0x2b4/0x3b0 [ath11k] + Call Trace: + + ? __die_body+0xae/0xb0 + ? page_fault_oops+0x381/0x3e0 + ? exc_page_fault+0x69/0xa0 + ? asm_exc_page_fault+0x22/0x30 + ? ath11k_hal_dump_srng_stats+0x2b4/0x3b0 [ath11k (HASH:6cea 4)] + ath11k_qmi_driver_event_work+0xbd/0x1050 [ath11k (HASH:6cea 4)] + worker_thread+0x389/0x930 + kthread+0x149/0x170 + +Clear per-list ->initialized flag in ath11k_hal_srng_deinit(). + +Signed-off-by: Sergey Senozhatsky +Reviewed-by: Baochen Qiang +Fixes: 5118935b1bc2 ("ath11k: dump SRNG stats during FW assert") +Link: https://patch.msgid.link/20250612084551.702803-1-senozhatsky@chromium.org +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/hal.c | 4 ++++ + 1 file changed, 4 insertions(+) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -1341,6 +1341,10 @@ EXPORT_SYMBOL(ath11k_hal_srng_init); + void ath11k_hal_srng_deinit(struct ath11k_base *ab) + { + struct ath11k_hal *hal = &ab->hal; ++ int i; ++ ++ for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) ++ ab->hal.srng_list[i].initialized = 0; + + ath11k_hal_unregister_srng_key(ab); + ath11k_hal_free_cont_rdp(ab); diff --git a/patches/ath11k/941-ath11k-fix_sleeping-in-atomic_in_ath11k_mac_op_set_bitrate_mask.patch b/patches/ath11k/941-ath11k-fix_sleeping-in-atomic_in_ath11k_mac_op_set_bitrate_mask.patch new file mode 100644 index 0000000..8340216 --- /dev/null +++ b/patches/ath11k/941-ath11k-fix_sleeping-in-atomic_in_ath11k_mac_op_set_bitrate_mask.patch @@ -0,0 +1,67 @@ +From 6bdef22d540258ca06f079f7b6ae100669a19b47 Mon Sep 17 00:00:00 2001 +From: Baochen Qiang +Date: Tue, 3 Jun 2025 10:25:28 +0800 +Subject: wifi: ath11k: fix sleeping-in-atomic in + ath11k_mac_op_set_bitrate_mask() + +[ Upstream commit 65c12b104cb942d588a1a093acc4537fb3d3b129 ] + +ath11k_mac_disable_peer_fixed_rate() is passed as the iterator to +ieee80211_iterate_stations_atomic(). Note in this case the iterator is +required to be atomic, however ath11k_mac_disable_peer_fixed_rate() does +not follow it as it might sleep. Consequently below warning is seen: + +BUG: sleeping function called from invalid context at wmi.c:304 +Call Trace: + + dump_stack_lvl + __might_resched.cold + ath11k_wmi_cmd_send + ath11k_wmi_set_peer_param + ath11k_mac_disable_peer_fixed_rate + ieee80211_iterate_stations_atomic + ath11k_mac_op_set_bitrate_mask.cold + +Change to ieee80211_iterate_stations_mtx() to fix this issue. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Baochen Qiang +Link: https://patch.msgid.link/20250603-ath11k-use-non-atomic-iterator-v1-1-d75762068d56@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/mac.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8740,9 +8740,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie + arvif->vdev_id, ret); + return ret; + } +- ieee80211_iterate_stations_atomic(ar->hw, +- ath11k_mac_disable_peer_fixed_rate, +- arvif); ++ ieee80211_iterate_stations_mtx(ar->hw, ++ ath11k_mac_disable_peer_fixed_rate, ++ arvif); + } else if (ath11k_mac_bitrate_mask_get_single_nss(ar, arvif, band, mask, + &single_nss)) { + rate = WMI_FIXED_RATE_NONE; +@@ -8809,9 +8809,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie + } + + mutex_lock(&ar->conf_mutex); +- ieee80211_iterate_stations_atomic(ar->hw, +- ath11k_mac_disable_peer_fixed_rate, +- arvif); ++ ieee80211_iterate_stations_mtx(ar->hw, ++ ath11k_mac_disable_peer_fixed_rate, ++ arvif); + + arvif->bitrate_mask = *mask; + ieee80211_iterate_stations_atomic(ar->hw, diff --git a/patches/ath11k/942-ath11k-fix_dest_ring-buffer_corruption.patch b/patches/ath11k/942-ath11k-fix_dest_ring-buffer_corruption.patch new file mode 100644 index 0000000..e477103 --- /dev/null +++ b/patches/ath11k/942-ath11k-fix_dest_ring-buffer_corruption.patch @@ -0,0 +1,83 @@ +From 0f708ced89758247f5d2d70def00e7c1c80ff557 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 4 Jun 2025 16:34:53 +0200 +Subject: wifi: ath11k: fix dest ring-buffer corruption + +commit 8c1ba5091fa9a2d1478da63173b16a701bdf86bb upstream. + +Add the missing memory barrier to make sure that destination ring +descriptors are read after the head pointers to avoid using stale data +on weakly ordered architectures like aarch64. + +The barrier is added to the ath11k_hal_srng_access_begin() helper for +symmetry with follow-on fixes for source ring buffer corruption which +will add barriers to ath11k_hal_srng_access_end(). + +Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Cc: stable@vger.kernel.org # 5.6 +Signed-off-by: Johan Hovold +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20250604143457.26032-2-johan+linaro@kernel.org +Signed-off-by: Jeff Johnson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath11k/ce.c | 3 --- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 --- + drivers/net/wireless/ath/ath11k/hal.c | 12 +++++++++++- + 3 files changed, 11 insertions(+), 7 deletions(-) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/ce.c ++++ b/drivers/net/wireless/ath/ath11k/ce.c +@@ -393,9 +393,6 @@ static int ath11k_ce_completed_recv_next + goto err; + } + +- /* Make sure descriptor is read after the head pointer. */ +- dma_rmb(); +- + *nbytes = ath11k_hal_ce_dst_status_get_length(desc); + + *skb = pipe->dest_ring->skb[sw_index]; +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -2650,9 +2650,6 @@ int ath11k_dp_process_rx(struct ath11k_b + try_again: + ath11k_hal_srng_access_begin(ab, srng); + +- /* Make sure descriptor is read after the head pointer. */ +- dma_rmb(); +- + while (likely(desc = + (struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab, + srng))) { +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -823,13 +823,23 @@ u32 *ath11k_hal_srng_src_peek(struct ath + + void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng) + { ++ u32 hp; ++ + lockdep_assert_held(&srng->lock); + + if (srng->ring_dir == HAL_SRNG_DIR_SRC) { + srng->u.src_ring.cached_tp = + *(volatile u32 *)srng->u.src_ring.tp_addr; + } else { +- srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr); ++ hp = READ_ONCE(*srng->u.dst_ring.hp_addr); ++ ++ if (hp != srng->u.dst_ring.cached_hp) { ++ srng->u.dst_ring.cached_hp = hp; ++ /* Make sure descriptor is read after the head ++ * pointer. ++ */ ++ dma_rmb(); ++ } + + /* Try to prefetch the next descriptor in the ring */ + if (srng->flags & HAL_SRNG_FLAGS_CACHED) diff --git a/patches/ath11k/943-ath11k-fix_source_ring-buffer_corruption.patch b/patches/ath11k/943-ath11k-fix_source_ring-buffer_corruption.patch new file mode 100644 index 0000000..f9cbe10 --- /dev/null +++ b/patches/ath11k/943-ath11k-fix_source_ring-buffer_corruption.patch @@ -0,0 +1,56 @@ +From eed5fcf4a3d20fdbd9af2e602eab2b581264822f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 4 Jun 2025 16:34:56 +0200 +Subject: wifi: ath11k: fix source ring-buffer corruption + +commit 6efa0df54022c6c9fd4d294b87622c7fcdc418c8 upstream. + +Add the missing memory barrier to make sure that LMAC source ring +descriptors are written before updating the head pointer to avoid +passing stale data to the firmware on weakly ordered architectures like +aarch64. + +Note that non-LMAC rings use MMIO write accessors which have the +required write memory barrier. + +Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Cc: stable@vger.kernel.org # 5.6 +Signed-off-by: Johan Hovold +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20250604143457.26032-5-johan+linaro@kernel.org +Signed-off-by: Jeff Johnson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath11k/hal.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -862,7 +862,11 @@ void ath11k_hal_srng_access_end(struct a + if (srng->ring_dir == HAL_SRNG_DIR_SRC) { + srng->u.src_ring.last_tp = + *(volatile u32 *)srng->u.src_ring.tp_addr; +- *srng->u.src_ring.hp_addr = srng->u.src_ring.hp; ++ /* Make sure descriptor is written before updating the ++ * head pointer. ++ */ ++ dma_wmb(); ++ WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); + } else { + srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; + *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; +@@ -871,6 +875,10 @@ void ath11k_hal_srng_access_end(struct a + if (srng->ring_dir == HAL_SRNG_DIR_SRC) { + srng->u.src_ring.last_tp = + *(volatile u32 *)srng->u.src_ring.tp_addr; ++ /* Assume implementation use an MMIO write accessor ++ * which has the required wmb() so that the descriptor ++ * is written before the updating the head pointer. ++ */ + ath11k_hif_write32(ab, + (unsigned long)srng->u.src_ring.hp_addr - + (unsigned long)ab->mem, diff --git a/patches/ath11k/944-ath11k-fix_dest_ring-buffer_corruption_when_ring_is_full.patch b/patches/ath11k/944-ath11k-fix_dest_ring-buffer_corruption_when_ring_is_full.patch new file mode 100644 index 0000000..e0e5348 --- /dev/null +++ b/patches/ath11k/944-ath11k-fix_dest_ring-buffer_corruption_when_ring_is_full.patch @@ -0,0 +1,61 @@ +From 6fc2589aae91818dd1183a589ab97d8e5c25364e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 4 Jun 2025 16:34:57 +0200 +Subject: wifi: ath11k: fix dest ring-buffer corruption when ring is full + +commit aa6956150f820e6a6deba44be325ddfcb5b10f88 upstream. + +Add the missing memory barriers to make sure that destination ring +descriptors are read before updating the tail pointer (and passing +ownership to the device) to avoid memory corruption on weakly ordered +architectures like aarch64 when the ring is full. + +Tested-on: WCN6855 hw2.1 WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Cc: stable@vger.kernel.org # 5.6 +Signed-off-by: Johan Hovold +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20250604143457.26032-6-johan+linaro@kernel.org +Signed-off-by: Jeff Johnson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath11k/hal.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -854,7 +854,6 @@ void ath11k_hal_srng_access_end(struct a + { + lockdep_assert_held(&srng->lock); + +- /* TODO: See if we need a write memory barrier here */ + if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) { + /* For LMAC rings, ring pointer updates are done through FW and + * hence written to a shared memory location that is read by FW +@@ -869,7 +868,11 @@ void ath11k_hal_srng_access_end(struct a + WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); + } else { + srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; +- *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; ++ /* Make sure descriptor is read before updating the ++ * tail pointer. ++ */ ++ dma_mb(); ++ WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp); + } + } else { + if (srng->ring_dir == HAL_SRNG_DIR_SRC) { +@@ -885,6 +888,10 @@ void ath11k_hal_srng_access_end(struct a + srng->u.src_ring.hp); + } else { + srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; ++ /* Make sure descriptor is read before updating the ++ * tail pointer. ++ */ ++ mb(); + ath11k_hif_write32(ab, + (unsigned long)srng->u.dst_ring.tp_addr - + (unsigned long)ab->mem, diff --git a/patches/ath11k/945-ath11k-fix_group_data_packet_drops_during_rekey.patch b/patches/ath11k/945-ath11k-fix_group_data_packet_drops_during_rekey.patch new file mode 100644 index 0000000..b7b66ef --- /dev/null +++ b/patches/ath11k/945-ath11k-fix_group_data_packet_drops_during_rekey.patch @@ -0,0 +1,237 @@ +From 9a394fd149502394c20dc2ebecb8acfde6f6aeac Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Sun, 10 Aug 2025 22:30:18 +0530 +Subject: wifi: ath11k: fix group data packet drops during rekey +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 97acb0259cc9cbfbd7ab689e25684f3d8ce10e26 ] + +During GTK rekey, mac80211 issues a clear key (if the old key exists) +followed by an install key operation in the same context. This causes +ath11k to send two WMI commands in quick succession: one to clear the +old key and another to install the new key in the same slot. + +Under certain conditions—especially under high load or time sensitive +scenarios, firmware may process these commands asynchronously in a way +that firmware assumes the key is cleared whereas hardware has a valid key. +This inconsistency between hardware and firmware leads to group addressed +packet drops. Only setting the same key again can restore a valid key in +firmware and allow packets to be transmitted. + +This issue remained latent because the host's clear key commands were +not effective in firmware until commit 436a4e886598 ("ath11k: clear the +keys properly via DISABLE_KEY"). That commit enabled the host to +explicitly clear group keys, which inadvertently exposed the race. + +To mitigate this, restrict group key clearing across all modes (AP, STA, +MESH). During rekey, the new key can simply be set on top of the previous +one, avoiding the need for a clear followed by a set. + +However, in AP mode specifically, permit group key clearing when no +stations are associated. This exception supports transitions from secure +modes (e.g., WPA2/WPA3) to open mode, during which all associated peers +are removed and the group key is cleared as part of the transition. + +Add a per-BSS station counter to track the presence of stations during +set key operations. Also add a reset_group_keys flag to track the key +re-installation state and avoid repeated installation of the same key +when the number of connected stations transitions to non-zero within a +rekey period. + +Additionally, for AP and Mesh modes, when the first station associates, +reinstall the same group key that was last set. This ensures that the +firmware recovers from any race that may have occurred during a previous +key clear when no stations were associated. + +This change ensures that key clearing is permitted only when no clients +are connected, avoiding packet loss while enabling dynamic security mode +transitions. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41 + +Reported-by: Steffen Moser +Closes: https://lore.kernel.org/linux-wireless/c6366409-9928-4dd7-bf7b-ba7fcf20eabf@steffen-moser.de +Fixes: 436a4e886598 ("ath11k: clear the keys properly via DISABLE_KEY") +Signed-off-by: Rameshkumar Sundaram +Tested-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250810170018.1124014-1-rameshkumar.sundaram@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/core.h | 2 + + drivers/net/wireless/ath/ath11k/mac.c | 111 ++++++++++++++++++++++++++++++--- + 2 files changed, 104 insertions(+), 9 deletions(-) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -414,6 +414,8 @@ struct ath11k_vif { + bool do_not_send_tmpl; + struct ath11k_arp_ns_offload arp_ns_offload; + struct ath11k_rekey_data rekey_data; ++ u32 num_stations; ++ bool reinstall_group_keys; + + struct ath11k_reg_tpc_power_info reg_tpc_info; + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct + return first_errno; + } + ++static int ath11k_set_group_keys(struct ath11k_vif *arvif) ++{ ++ struct ath11k *ar = arvif->ar; ++ struct ath11k_base *ab = ar->ab; ++ const u8 *addr = arvif->bssid; ++ int i, ret, first_errno = 0; ++ struct ath11k_peer *peer; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath11k_peer_find(ab, arvif->vdev_id, addr); ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (!peer) ++ return -ENOENT; ++ ++ for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { ++ struct ieee80211_key_conf *key = peer->keys[i]; ++ ++ if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) ++ continue; ++ ++ ret = ath11k_install_key(arvif, key, SET_KEY, addr, ++ WMI_KEY_GROUP); ++ if (ret < 0 && first_errno == 0) ++ first_errno = ret; ++ ++ if (ret < 0) ++ ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n", ++ i, arvif->vdev_id, ret); ++ } ++ ++ return first_errno; ++} ++ + static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +@@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_peer *peer; + struct ath11k_sta *arsta; ++ bool is_ap_with_no_sta; + const u8 *peer_addr; + int ret = 0; + u32 flags = 0; +@@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct + else + flags |= WMI_KEY_GROUP; + +- ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags); +- if (ret) { +- ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret); +- goto exit; +- } ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n", ++ cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id, ++ flags, arvif->vdev_type, arvif->num_stations); ++ ++ /* Allow group key clearing only in AP mode when no stations are ++ * associated. There is a known race condition in firmware where ++ * group addressed packets may be dropped if the key is cleared ++ * and immediately set again during rekey. ++ * ++ * During GTK rekey, mac80211 issues a clear key (if the old key ++ * exists) followed by an install key operation for same key ++ * index. This causes ath11k to send two WMI commands in quick ++ * succession: one to clear the old key and another to install the ++ * new key in the same slot. ++ * ++ * Under certain conditions—especially under high load or time ++ * sensitive scenarios, firmware may process these commands ++ * asynchronously in a way that firmware assumes the key is ++ * cleared whereas hardware has a valid key. This inconsistency ++ * between hardware and firmware leads to group addressed packet ++ * drops after rekey. ++ * Only setting the same key again can restore a valid key in ++ * firmware and allow packets to be transmitted. ++ * ++ * There is a use case where an AP can transition from Secure mode ++ * to open mode without a vdev restart by just deleting all ++ * associated peers and clearing key, Hence allow clear key for ++ * that case alone. Mark arvif->reinstall_group_keys in such cases ++ * and reinstall the same key when the first peer is added, ++ * allowing firmware to recover from the race if it had occurred. ++ */ + +- ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key); +- if (ret) { +- ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret); +- goto exit; ++ is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP && ++ !arvif->num_stations); ++ if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) { ++ ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags); ++ if (ret) { ++ ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret); ++ goto exit; ++ } ++ ++ ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key); ++ if (ret) { ++ ath11k_warn(ab, "failed to offload PN replay detection %d\n", ++ ret); ++ goto exit; ++ } ++ ++ if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta) ++ arvif->reinstall_group_keys = true; + } + + spin_lock_bh(&ab->base_lock); +@@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(s + return -ENOBUFS; + + ar->num_stations++; ++ arvif->num_stations++; + + return 0; + } +@@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations( + return; + + ar->num_stations--; ++ arvif->num_stations--; + } + + static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar, +@@ -9536,6 +9614,21 @@ static int ath11k_mac_station_add(struct + goto exit; + } + ++ /* Driver allows the DEL KEY followed by SET KEY sequence for ++ * group keys for only when there is no clients associated, if at ++ * all firmware has entered the race during that window, ++ * reinstalling the same key when the first sta connects will allow ++ * firmware to recover from the race. ++ */ ++ if (arvif->num_stations == 1 && arvif->reinstall_group_keys) { ++ ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n", ++ arvif->vdev_id); ++ ret = ath11k_set_group_keys(arvif); ++ if (ret) ++ goto dec_num_station; ++ arvif->reinstall_group_keys = false; ++ } ++ + arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); + if (!arsta->rx_stats) { + ret = -ENOMEM; diff --git a/patches/ath11k/946-ath11k-fix_NULL_dereference_in_ath11k_qmi_m3_load.patch b/patches/ath11k/946-ath11k-fix_NULL_dereference_in_ath11k_qmi_m3_load.patch new file mode 100644 index 0000000..258a94c --- /dev/null +++ b/patches/ath11k/946-ath11k-fix_NULL_dereference_in_ath11k_qmi_m3_load.patch @@ -0,0 +1,40 @@ +From 888830b2cbc035838bebefe94502976da94332a5 Mon Sep 17 00:00:00 2001 +From: Matvey Kovalev +Date: Wed, 17 Sep 2025 22:20:01 +0300 +Subject: wifi: ath11k: fix NULL dereference in ath11k_qmi_m3_load() + +commit 3fd2ef2ae2b5c955584a3bee8e83ae7d7a98f782 upstream. + +If ab->fw.m3_data points to data, then fw pointer remains null. +Further, if m3_mem is not allocated, then fw is dereferenced to be +passed to ath11k_err function. + +Replace fw->size by m3_len. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 7db88b962f06 ("wifi: ath11k: add firmware-2.bin support") +Cc: stable@vger.kernel.org +Signed-off-by: Matvey Kovalev +Reviewed-by: Baochen Qiang +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250917192020.1340-1-matvey.kovalev@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath11k/qmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +(limited to 'drivers/net/wireless/ath/ath11k') + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2576,7 +2576,7 @@ static int ath11k_qmi_m3_load(struct ath + GFP_KERNEL); + if (!m3_mem->vaddr) { + ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n", +- fw->size); ++ m3_len); + ret = -ENOMEM; + goto out; + } diff --git a/patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch b/patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch new file mode 100644 index 0000000..725b9df --- /dev/null +++ b/patches/ath11k/983-ath11k-Enable-VHT-for-2G.patch @@ -0,0 +1,35 @@ +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -2868,9 +2868,9 @@ static void ath11k_peer_assoc_h_phymode( + } else if (sta->deflink.vht_cap.vht_supported && + !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) { + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) +- phymode = MODE_11AC_VHT40; ++ phymode = MODE_11AC_VHT40_2G; + else +- phymode = MODE_11AC_VHT20; ++ phymode = MODE_11AC_VHT20_2G; + } else if (sta->deflink.ht_cap.ht_supported && + !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) { + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) +@@ -5547,6 +5547,9 @@ static void ath11k_mac_setup_ht_vht_cap( + *ht_cap_info = ht_cap; + band->ht_cap = ath11k_create_ht_cap(ar, ht_cap, + rate_cap_rx_chainmask); ++ ++ band->vht_cap = ath11k_create_vht_cap(ar, rate_cap_tx_chainmask, ++ rate_cap_rx_chainmask); + } + + if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP && +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -411,6 +411,8 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(st + * handled. + */ + if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_2G_CAP) { ++ pdev_cap->vht_cap = mac_phy_caps->vht_cap_info_2g; ++ pdev_cap->vht_mcs = mac_phy_caps->vht_supp_mcs_2g; + pdev_cap->tx_chain_mask = mac_phy_caps->tx_chain_mask_2g; + pdev_cap->rx_chain_mask = mac_phy_caps->rx_chain_mask_2g; + } diff --git a/patches/ath11k/984-ath11k-workaround-for-memory-leak.patch b/patches/ath11k/984-ath11k-workaround-for-memory-leak.patch new file mode 100644 index 0000000..0efeea1 --- /dev/null +++ b/patches/ath11k/984-ath11k-workaround-for-memory-leak.patch @@ -0,0 +1,13 @@ +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -371,8 +371,8 @@ int ath11k_dp_rxbufs_replenish(struct at + num_remain = req_entries; + + while (num_remain > 0) { +- skb = dev_alloc_skb(DP_RX_BUFFER_SIZE + +- DP_RX_BUFFER_ALIGN_SIZE); ++ skb = alloc_skb(DP_RX_BUFFER_SIZE + ++ DP_RX_BUFFER_ALIGN_SIZE, GFP_ATOMIC); + if (!skb) + break; + diff --git a/patches/ath12k/100-ath12k-prevent-ltssm-startup-crash.patch b/patches/ath12k/100-ath12k-prevent-ltssm-startup-crash.patch new file mode 100644 index 0000000..2209878 --- /dev/null +++ b/patches/ath12k/100-ath12k-prevent-ltssm-startup-crash.patch @@ -0,0 +1,17 @@ +Fix ltssm crashes on BPI-Rx boards. +Seems read32/write32 using wrong address which +is not a problem on x86/64 PCI controllers. +But have issues on BPI-Rx boards. + +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -279,6 +279,9 @@ static void ath12k_pci_enable_ltssm(stru + u32 val; + int i; + ++ /* Prevent startup crash on BPI-Rx */ ++ return; ++ + val = ath12k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM); + + /* PCIE link seems very unstable after the Hot Reset*/ diff --git a/patches/ath12k/102-wifi-ath12k-limit-WMI_SCAN_CHAN_LIST_CMDID-arg.patch b/patches/ath12k/102-wifi-ath12k-limit-WMI_SCAN_CHAN_LIST_CMDID-arg.patch new file mode 100644 index 0000000..9bbc752 --- /dev/null +++ b/patches/ath12k/102-wifi-ath12k-limit-WMI_SCAN_CHAN_LIST_CMDID-arg.patch @@ -0,0 +1,153 @@ +From patchwork Mon Mar 10 13:28:18 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Mantas +X-Patchwork-Id: 14010032 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mail-lf1-f41.google.com (mail-lf1-f41.google.com + [209.85.167.41]) + (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2ADD522A4DA + for ; Mon, 10 Mar 2025 13:28:47 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=209.85.167.41 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1741613330; cv=none; + b=Vx8zckt7S92zrauuzzoNjX/1eXhlbq+4R3uNXCWPCBFXXHBuAHrmXrDOQILh1g+IfyWOgpyXyibTTkLg6IWREXcA/OjV+V9ehNaQaHJAt4D14uxuNW6uIDA56myF+bhdmiZnfGZfK3puVBjeCAMbZwGhc81dTR3RaEhKYP93Wcg= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1741613330; c=relaxed/simple; + bh=yRMCaDQnvsF6vQ/w9rLRB/etZre1sSzpWUDTNGX0zAk=; + h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; + b=rFopB9f+nOXbmGbGXoo4SeBAV82xQ6nydiMDCiYAw7sELURejS0lK9xQZolnRGeyNtHnQgix39lrcilr6cdvGMhaziXzS6RYlY2WyoHTMxHwYGUIa9McnJ1AkCczdVv6SgeNUlVVEgAZBqH0Q2pmd5b91h/PMc/aPdQm9SQY8IU= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=quarantine dis=none) header.from=8devices.com; + spf=pass smtp.mailfrom=8devices.com; + dkim=pass (2048-bit key) header.d=8devices.com header.i=@8devices.com + header.b=LitRbtOU; arc=none smtp.client-ip=209.85.167.41 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=quarantine dis=none) header.from=8devices.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=8devices.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=8devices.com header.i=@8devices.com + header.b="LitRbtOU" +Received: by mail-lf1-f41.google.com with SMTP id + 2adb3069b0e04-5499c5d9691so1866539e87.2 + for ; + Mon, 10 Mar 2025 06:28:47 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=8devices.com; s=8devices; t=1741613326; x=1742218126; + darn=vger.kernel.org; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:from:to:cc:subject:date:message-id:reply-to; + bh=6+w3029kfHch5SeD/z0zur2K64cd98za9hhmN/ji0MY=; + b=LitRbtOUxDhUPycKFo/pzuJu9Y11QmpYSvOmkgM9TcNEOsBvLk8z0EJ7+xy24ijRGJ + Xz16V9Z1kJGkXBK90klI6s3RjVBQf+dxf37t2kdQWdrgOE2VhXjnnV5zP7odCkMmOViw + 2UmKSvagsxc6KojE2OYyd+vR3hmL+4fCtegorXMaRrf0Brje8XJmViAUgbc+IAtfL0Ao + pnig300fAb4WbnmIJIRiOUKoTESjbJRkUehGJkhe1ztiPE1F86AVMXw5IrDBR/WtMin1 + 9nYYDqfSGvI7fOvfStfZ9hS0ShIhBNd5naccyQ7c0xSTvXJ51vUvNvdZuufm9OKsbQ99 + nh4g== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1741613326; x=1742218126; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:x-gm-message-state:from:to:cc:subject:date:message-id + :reply-to; + bh=6+w3029kfHch5SeD/z0zur2K64cd98za9hhmN/ji0MY=; + b=Gx+AX3aIV66kzjGLGOToc2CuQrnfaWn43yZW2rgRpKJv03162undTbo+SdaI8s+8mY + aKrYsNOOqI4h6pHCZsVkBzqVh5ZOs+xJbJaHEETGzyBYA2sy0bdDwDUr0rIzJUD8ZYiw + 736zfMRE2rxfOLoVIcfBLXMUcR2d63n/4wxgr1s5HVV3o8uEZ5gxNDnz5p/QabiWbT3m + AMSVVaOBUTRnd9GcZhzYfKboT7SNrTJz0emqSWPKCWfm8dYIzH3TuIGULfRu5UA1/Y2H + Q6ZbLmcYu5+VDKCtQl4nSmun3WUNAyPoeg5PCB1YcuCpqKcjU8l5Kkn+JxNjYAG432us + Z5xQ== +X-Forwarded-Encrypted: i=1; + AJvYcCVigvWgctGNxtYGpBtNhTPBpQPHa7l14ZVktj/Oe1W8p1xwSIjIViAk2X3sDC23bbrmI41TVZbgJZDGCMFJ6g==@vger.kernel.org +X-Gm-Message-State: AOJu0YxJFjAixTwr8dSwTYmdvbVzm/jbyVk+gQV6pF/9Vep5xeVdJMWa + TE+4MHJDPdO8dA16Yn/y5c8pLBEYKqRlo8uDHNKV6e5ldbv18Xv6bR163j+rVCQ= +X-Gm-Gg: ASbGncsUwV1fquQPNOfmTge/yCSzRhyC7+A8STTBe3n+C2XDK1UV8IswQL5UEXlb268 + mumVPzu1Ex8+Nh+quKWT+CIR3WR0NRXm1oiG0N+Cu2Mm4cm4mipqrV9Yxd6x5OMsG32XKd6r0iQ + gr7joJETyo6k1TGc6i0LyoIabLOCc7Nkeu7BD+URUnBvoeQyXBdJpX0bbdvANKW5DrUeX1GkUA7 + 0o4dZYtRola31Z1W9xZMdSefhmI4zZE4uy/RyR/FkQq2Zqk9FGct8DOKoHpOPa0DHVMy0lQAiNI + KNg6OYtuJY+/6TpDoZzNpooiLi29WL6hqlpkmlZeluuCBG6HlSbZTQ== +X-Google-Smtp-Source: + AGHT+IGIixTut4yqDWp69RPz6EjMMq4lD94Ez1yhsRnow6NgvTk6WmKPLFavYgOJC+xGczTQmaocLw== +X-Received: by 2002:a05:6512:1112:b0:549:5850:f275 with SMTP id + 2adb3069b0e04-54990ec8e60mr4354451e87.50.1741613326121; + Mon, 10 Mar 2025 06:28:46 -0700 (PDT) +Received: from [127.0.1.1] ([78.62.132.154]) + by smtp.gmail.com with ESMTPSA id + 2adb3069b0e04-5498b1bcaecsm1460408e87.200.2025.03.10.06.28.45 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Mon, 10 Mar 2025 06:28:45 -0700 (PDT) +From: Mantas Pucka +Date: Mon, 10 Mar 2025 15:28:18 +0200 +Subject: [PATCH ath-next] wifi: ath12k: limit WMI_SCAN_CHAN_LIST_CMDID + argument size +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Message-Id: <20250310-limit-wmi-chanlist-v1-1-8f0fb45459a7@8devices.com> +X-B4-Tracking: v=1; b=H4sIAPHozmcC/x2MSwqEMBAFryK9tiGJ+MGriIuMtvpAM0MSHEG8u + 9FNQVG8d1IQDwnUZid52RHwdUl0ntGwWDcLY0xORplSFVrxig2R/xv46StCZF0Pn2Y0ibaiNPx + 5mXC8px3ZuLCTI1J/XTfUqQSebgAAAA== +X-Change-ID: 20250310-limit-wmi-chanlist-17cb8d27cba6 +To: ath12k@lists.infradead.org +Cc: Johannes Berg , + Jeff Johnson , linux-wireless@vger.kernel.org, + linux-kernel@vger.kernel.org, Mantas Pucka +X-Mailer: b4 0.14.2 + +When using BDF with both 5GHz and 6GHz bands enabled on QCN9274, interface +fails to start. It happens because FW fails to process +WMI_SCAN_CHAN_LIST_CMDID with argument size >2048, resulting in a command +timeout. The current code allows splitting channel list across multiple WMI +commands but uses WMI max_msg_len (4096) as chunk size, which is still too +large. + +Fix this by limiting the number of channels sent at once, using the value +specified in WMI interface description [1]. + +[1] https://git.codelinaro.org/clo/qsdk/platform/vendor/qcom-opensource/wlan/fw-api/-/blob/NHSS.QSDK.13.0.0.6/fw/wmi_unified.h#L6459 + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Mantas Pucka +--- + drivers/net/wireless/ath/ath12k/wmi.c | 3 +++ + drivers/net/wireless/ath/ath12k/wmi.h | 2 ++ + 2 files changed, 5 insertions(+) + + +--- +base-commit: 42aa76e608ca845c98e79f9e23af0bdb07b2eb1d +change-id: 20250310-limit-wmi-chanlist-17cb8d27cba6 + +Best regards, + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2832,6 +2832,9 @@ int ath12k_wmi_send_scan_chan_list_cmd(s + max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) / + sizeof(*chan_info); + ++ if (max_chan_limit > WMI_MAX_NUM_CHAN_PER_WMI_CMD) ++ max_chan_limit = WMI_MAX_NUM_CHAN_PER_WMI_CMD; ++ + num_send_chans = min(arg->nallchans, max_chan_limit); + + arg->nallchans -= num_send_chans; +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3947,6 +3947,8 @@ struct wmi_stop_scan_cmd { + __le32 pdev_id; + } __packed; + ++#define WMI_MAX_NUM_CHAN_PER_WMI_CMD 58 ++ + struct ath12k_wmi_scan_chan_list_arg { + u32 pdev_id; + u16 nallchans; diff --git a/patches/ath12k/103-wifi-ath12k-fix-5GHz-operation-on-wideband-QCN.patch b/patches/ath12k/103-wifi-ath12k-fix-5GHz-operation-on-wideband-QCN.patch new file mode 100644 index 0000000..71b8f86 --- /dev/null +++ b/patches/ath12k/103-wifi-ath12k-fix-5GHz-operation-on-wideband-QCN.patch @@ -0,0 +1,137 @@ +From patchwork Thu Mar 13 09:00:56 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Mantas +X-Patchwork-Id: 14014575 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mail-lf1-f49.google.com (mail-lf1-f49.google.com + [209.85.167.49]) + (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id F210C2641F0 + for ; Thu, 13 Mar 2025 09:01:28 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=209.85.167.49 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1741856491; cv=none; + b=CeFjBZstZXxg4oQQPPON0u0Mw9kvUaCubWSfpcWvN2italvlwccDBr+izqIzCXwxYaoAedVR6iHEQv+LBtIHOsMWHOCI9E6jYAPqjbEUEU0RMdvujKLVFvFXYR4UaRDAMzDGMlFF1qc0pY0sYR4FYfFBBQOarHn2sjZ/csIyj4k= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1741856491; c=relaxed/simple; + bh=oLhlWw1tOovRHEGC4gsbi6BHKYXLNDYOrtVP3tTS5nE=; + h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; + b=baAfN8drFOEwQR9LVuWoVsd3jkMbQECK7Zuc68EzbbJwM4Zb0tbziTk1vvqED+f9JPOMbjRyjvV1hvy3svqZr7OuTZJdSM41D+DsbHvw0jEhaRlKwzpLWuOn9lu56ahcAsvx4A4JRawEK90smoYpejhxkdlSrxqRBh1ey3RwmQU= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=quarantine dis=none) header.from=8devices.com; + spf=pass smtp.mailfrom=8devices.com; + dkim=pass (2048-bit key) header.d=8devices.com header.i=@8devices.com + header.b=FdBxu3P+; arc=none smtp.client-ip=209.85.167.49 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=quarantine dis=none) header.from=8devices.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=8devices.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=8devices.com header.i=@8devices.com + header.b="FdBxu3P+" +Received: by mail-lf1-f49.google.com with SMTP id + 2adb3069b0e04-54943bb8006so648002e87.0 + for ; + Thu, 13 Mar 2025 02:01:28 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=8devices.com; s=8devices; t=1741856487; x=1742461287; + darn=vger.kernel.org; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:from:to:cc:subject:date:message-id:reply-to; + bh=uj7GGUjO2Cb2hoHrzMda/fIIQwFl12ddzGuw5jrHW8M=; + b=FdBxu3P+gf3qNd4jxSOCYUJ1meLFYAm0ou6lnEyomeeXDBFwITM6FM0cgBdXgmkLWZ + ZKowNImwE9FKqNGxpg2tZ4obR9aM7HzzkxV3TE+1aIiocbr/5xyXQU+/AUvaM3vui/8d + SFiwhX9FwFKdrYi1Og4XFD2aBhA5Fzp0U27grJYGTLchEfkr9Om43y3vZ7w2ENEBU0SO + 7NFmSwx7BmflIybP2sGCUzjacGQzzec0zz256EY7GpZH9r19jgWiCe1YGWdlxDaRhWze + xV4okbZKydpYlUU/qGsgn23cRQuFCvMobvfkmTwsGYwlN4bAzq/cHw83YEFrUzYOngZK + z7bg== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1741856487; x=1742461287; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:x-gm-message-state:from:to:cc:subject:date:message-id + :reply-to; + bh=uj7GGUjO2Cb2hoHrzMda/fIIQwFl12ddzGuw5jrHW8M=; + b=PhLIANoGtdl34d9fFH7uxPyg1K5yPGRwimsWPVhHon98V9QP64+qUbifocbfojxz8u + NEVzhOx0kfmsmkBxUzuRCu6xuTAF8LmjBpAJJxo3/4nqY67np8iZt/MITzx6egbMOUAs + txqj0rzXwr55N/9yAD/QuD6bBcd8PcNMPp0CjFAt39AyK6De3BEIcA7b/eLoY3lifaxJ + 9U5ZZ/dHXwSIr9xuE1EB6pT5FbHcI8iWJTDJ8NdBcmWC8qtGAAMzlzWqHU0nOAJEjwEc + T+oaJr8fTAgq4B5OvS1cNClscZHvoM3zlIoczwPPoBZCtUi2gThz9R4BrBxepdoZl1qq + NZQA== +X-Forwarded-Encrypted: i=1; + AJvYcCUSbJyRkEPLa3fw7FZX3Ci6+/o8dqI0hd6pkVT20pi6Ufgze7nBQXa+qdK3OM5Ng2TFBrym8JoyBo//MwDHng==@vger.kernel.org +X-Gm-Message-State: AOJu0Ywjzq2sFNyTMNPyxDt+721RyXdLbDPrF5PY3LnwpKaTfduyXkMF + K/7N3Cpb/71aQsMXwmIbXAOGeLVWLBQHdYnQLZlsCTjVNArIjgiX7tNB0Mq56+qYtR9PdMrBAt8 + m +X-Gm-Gg: ASbGncvDd0SdjhjPfzaKTXW4e0hclZuKu4pZ4d0XD5/Q6dnv09ZObgGjJbIRrAhYizp + zWc8CwidDk8UYPX/OhiAyDhS4XRKRy2QG03sZh17aHDhishhmCE+mcqe+YUM+F4ns/05sAR2MeP + wu/Rz6NS6UD4ihGNReTORGB3X4n9I5dgdNheFyqbrRX+Js4zXuvn1jgoEWawfovOu/4HAlnv+7p + 1ufgXBXJGVj6+OGzyNOyYloTB/Csok3zU9yBfrU+G19mpGaF86t/6yxmUIXCO+cWfbu2GIhVZp3 + RmSiDo/spnsvtYVGCPc6v9jALz83YcknTLkX8u+08AOkJKK7Mh8rKlCvbfZcB355 +X-Google-Smtp-Source: + AGHT+IE2NulrNIo+M5vahinpDWyI9BdSgzdREdo+l0AN7HhcxOd01ZBOpT3HYFht1EVpKj5T7Edrrw== +X-Received: by 2002:a05:6512:ba6:b0:549:8f21:bc0e with SMTP id + 2adb3069b0e04-54990eb1987mr9398593e87.32.1741856486697; + Thu, 13 Mar 2025 02:01:26 -0700 (PDT) +Received: from [127.0.1.1] ([78.62.132.154]) + by smtp.gmail.com with ESMTPSA id + 2adb3069b0e04-549ba88591csm142134e87.187.2025.03.13.02.01.25 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Thu, 13 Mar 2025 02:01:25 -0700 (PDT) +From: Mantas Pucka +Date: Thu, 13 Mar 2025 11:00:56 +0200 +Subject: [PATCH] wifi: ath12k: fix 5GHz operation on wideband QCN9274 + radios +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Message-Id: <20250313-ath12-wideband-caps-v1-1-23ac4247cd8a@8devices.com> +X-B4-Tracking: v=1; b=H4sIAMee0mcC/x3MQQqAIBBA0avErBvIsUi6SrSwHGs2FhoVhHdPW + r7F/y8kjsIJhuqFyJck2UOBqitYNhtWRnHFQA11jVYa7bkpwlsczzY4XOyRkNqZjOqNcZ6hlEd + kL89/HaecP+zWjGtlAAAA +X-Change-ID: 20250313-ath12-wideband-caps-24b281788dfe +To: ath12k@lists.infradead.org +Cc: Johannes Berg , + Jeff Johnson , linux-wireless@vger.kernel.org, + linux-kernel@vger.kernel.org, Mantas Pucka +X-Mailer: b4 0.14.2 + +Currently ath12k_mac_setup_ht_vht_cap() incorrectly assumes that QCN9274 +radios with 6GHz band can't support 5GHz as well. This prevents the +addition of HT and VHT capabilities for the 5GHz band. Since QCN9274 is +capable of operating in multiple bands, remove the 6GHz support check and +exception for single_pdev_only (i.e. WCN7850). + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Mantas Pucka +--- + drivers/net/wireless/ath/ath12k/mac.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + + +--- +base-commit: 42aa76e608ca845c98e79f9e23af0bdb07b2eb1d +change-id: 20250313-ath12-wideband-caps-24b281788dfe + +Best regards, + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6985,9 +6985,7 @@ static void ath12k_mac_setup_ht_vht_cap( + rate_cap_rx_chainmask); + } + +- if (cap->supported_bands & WMI_HOST_WLAN_5GHZ_CAP && +- (ar->ab->hw_params->single_pdev_only || +- !ar->supports_6ghz)) { ++ if (cap->supported_bands & WMI_HOST_WLAN_5GHZ_CAP) { + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; + ht_cap = cap->band[NL80211_BAND_5GHZ].ht_cap_info; + if (ht_cap_info) diff --git a/patches/ath12k/104-1-wifi-ath12k-push-HE-MU-MIMO-params-to-hardware.patch b/patches/ath12k/104-1-wifi-ath12k-push-HE-MU-MIMO-params-to-hardware.patch new file mode 100644 index 0000000..9fdc899 --- /dev/null +++ b/patches/ath12k/104-1-wifi-ath12k-push-HE-MU-MIMO-params-to-hardware.patch @@ -0,0 +1,484 @@ +From patchwork Wed May 21 22:45:31 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096118 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D9B523506D + for ; Wed, 21 May 2025 22:45:57 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867559; cv=none; + b=QXLrpE5trQYq3qZVPuAYdZ8IfmZi7XatjLyxn+9IZXmAWvPsCpT2EOrmLKoTKXH1gxwInwHzxiiwzDveDdYBFh2FGnxhAgdJlTBf1yChfW7+YndhKTtca3rP8z+Zt8QK48/n7gpmFEWkKGmxkG1DKIkCHgAZjD///ttubaAe2gc= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867559; c=relaxed/simple; + bh=wlnSlGktw4cBYqpNPJwSPfG4fkld5ABcJ0NmmjY/jLg=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=A4dIxT87Fh9Y97+jvDIVTPlA5cnixK5ZcCAl5lklS0dCWBpo0QkFFiYyRUSKso7kYaT6KFazofkMt8A2z/fDgN8gVZgqEkaXDFSRjqNWCtoplSK7qYryl88snzbQvzD52CbWKkX8yu2Qmd98HFrl2kg69o1e4wzXVcNc+fehea8= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=gwsO0461; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="gwsO0461" +Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LIZCMW000836; + Wed, 21 May 2025 22:45:53 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + jJ/9931jjDg+8neUbH09oigyzQwINmgJKgsYw6rWwPU=; b=gwsO0461NDm4hzMy + /aP5LNjbfqB08SmlMEzcZ/MRNS7Ffjdvz9gsUyJR4DOilx71C5MvB0ZBvxEJF6pg + qcU4QPZtOzyixWx+3vL6eh4Sdt/RN5AD/6U6TJEZCPwdJNLMD5uB2OQjP87NG9Wj + 2aEs+kb//lRXz6Gy5d7CCDW3+1KSDzgIg/cYJecPjWsMKbyCxTeFTIkkdonetQyz + PSzkIDi3IBnca94koYTQyFTVvpUVHpC3QAq+jM9+xQJOItRbDHZjdPjLG6q1ML4W + zYHODhd8LupxL323rnWJQxtYu5Ver7g2LgPW3npNz/JEdF2Hq9b8G0w5U8qVJVHr + 2nNuUA== +Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf6vbsd-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:53 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjqLl023280 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:52 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:51 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Muna Sinada , + "Jeff + Johnson" +Subject: [PATCH ath-next V14 1/9] wifi: ath12k: push HE MU-MIMO params to + hardware +Date: Wed, 21 May 2025 15:45:31 -0700 +Message-ID: <20250521224539.355985-2-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-GUID: Zzf2Q5y4JzSN5f1E_vlCnvLRODG4zasa +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfXyLZVeJQcQf0U + B/O6/0+L+1nXg6SAFSC1bdc8B/eF8RxRnvbbX+YkF3RG14/UHGCF654g8ZXTq8oTCDzm3x5wmAk + i8wAlv0otog8iYaicRd5q/x9Vynwlo0e67/iHhH1K0rxsp5yagZ6L3XLS82iLDPuXzHP7ylgo+I + D0c1CMcLo4bGNe421uQk2jqRij3j1iAoI0gGSwcQqHRucJQSYetF+SSp/oDox9Dn2TqOagngt4V + UxzAxO13SoH2X7RyWe5NxhfbEjOUmHjfodyJhBfIYh4s5SCx8IDUn6jSorAnl5mh1ZmAfISyZCC + UqoQ2LDdmGl1HT3d4xvb7/ah09ru4wukKEcvP+HDrow6Xn/WsfgmRy6xdRv5vdNODiEv64XOGHa + TxrJA2l36xRwX82xvkyUzyQ1sIeXwbvD0Wn//AQSmFVE0uMJHnCwRE1OYRGf9Dd2p/mfZfFh +X-Authority-Analysis: v=2.4 cv=fZOty1QF c=1 sm=1 tr=0 ts=682e57a1 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=-_O-Wy8N5QNPZvNXkjkA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-ORIG-GUID: Zzf2Q5y4JzSN5f1E_vlCnvLRODG4zasa +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + clxscore=1015 mlxscore=0 adultscore=0 spamscore=0 bulkscore=0 suspectscore=0 + malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999 + lowpriorityscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a + authcc= route=outbound adjust=0 reason=mlx scancount=1 + engine=8.19.0-2505160000 definitions=main-2505210226 + +Currently, only the HE IE in management frames is updated with +respect to MU-MIMO configurations, but this change is not +reflected in the hardware. Add support to propagate MU-MIMO +configurations to the hardware as well. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Muna Sinada +Signed-off-by: Muna Sinada +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/mac.c | 228 +++++++++++++++++--------- + drivers/net/wireless/ath/ath12k/mac.h | 15 ++ + drivers/net/wireless/ath/ath12k/wmi.h | 28 +--- + 3 files changed, 169 insertions(+), 102 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3173,6 +3173,125 @@ static u32 ath12k_mac_ieee80211_sta_bw_t + return bw; + } + ++static int ath12k_mac_set_he_txbf_conf(struct ath12k_link_vif *arvif) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k *ar = arvif->ar; ++ u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE; ++ u32 value = 0; ++ int ret; ++ struct ieee80211_bss_conf *link_conf; ++ ++ link_conf = ath12k_mac_get_link_bss_conf(arvif); ++ if (!link_conf) { ++ ath12k_warn(ar->ab, "unable to access bss link conf in txbf conf\n"); ++ return -EINVAL; ++ } ++ ++ if (!link_conf->he_support) ++ return 0; ++ ++ if (link_conf->he_su_beamformer) { ++ value |= u32_encode_bits(HE_SU_BFER_ENABLE, HE_MODE_SU_TX_BFER); ++ if (link_conf->he_mu_beamformer && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ value |= u32_encode_bits(HE_MU_BFER_ENABLE, HE_MODE_MU_TX_BFER); ++ } ++ ++ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) { ++ value |= u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) | ++ u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA); ++ ++ if (link_conf->he_full_ul_mumimo) ++ value |= u32_encode_bits(HE_UL_MUMIMO_ENABLE, HE_MODE_UL_MUMIMO); ++ ++ if (link_conf->he_su_beamformee) ++ value |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE); ++ } ++ ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n", ++ arvif->vdev_id, ret); ++ return ret; ++ } ++ ++ param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; ++ value = u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) | ++ u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE, ++ HE_TRIG_NONTRIG_SOUNDING_MODE); ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ param, value); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n", ++ arvif->vdev_id, ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ath12k_mac_vif_recalc_sta_he_txbf(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ieee80211_sta_he_cap *he_cap, ++ int *hemode) ++{ ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ieee80211_he_cap_elem he_cap_elem = {}; ++ struct ieee80211_sta_he_cap *cap_band; ++ struct cfg80211_chan_def def; ++ u8 link_id = arvif->link_id; ++ struct ieee80211_bss_conf *link_conf; ++ ++ link_conf = ath12k_mac_get_link_bss_conf(arvif); ++ if (!link_conf) { ++ ath12k_warn(ar->ab, "unable to access bss link conf in recalc txbf conf\n"); ++ return -EINVAL; ++ } ++ ++ if (!link_conf->he_support) ++ return 0; ++ ++ if (vif->type != NL80211_IFTYPE_STATION) ++ return -EINVAL; ++ ++ if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def))) ++ return -EINVAL; ++ ++ if (def.chan->band == NL80211_BAND_2GHZ) ++ cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap; ++ else ++ cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap; ++ ++ memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem)); ++ ++ *hemode = 0; ++ if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) { ++ if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info)) ++ *hemode |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE); ++ if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info)) ++ *hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE); ++ } ++ ++ if (vif->type != NL80211_IFTYPE_MESH_POINT) { ++ *hemode |= u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) | ++ u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA); ++ ++ if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info)) ++ if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info)) ++ *hemode |= u32_encode_bits(HE_UL_MUMIMO_ENABLE, ++ HE_MODE_UL_MUMIMO); ++ ++ if (u32_get_bits(*hemode, HE_MODE_MU_TX_BFEE)) ++ *hemode |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE); ++ ++ if (u32_get_bits(*hemode, HE_MODE_MU_TX_BFER)) ++ *hemode |= u32_encode_bits(HE_SU_BFER_ENABLE, HE_MODE_SU_TX_BFER); ++ } ++ ++ return 0; ++} ++ + static void ath12k_bss_assoc(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *bss_conf) +@@ -3187,6 +3306,7 @@ static void ath12k_bss_assoc(struct ath1 + struct ath12k_sta *ahsta; + struct ath12k_peer *peer; + bool is_auth = false; ++ u32 hemode = 0; + int ret; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); +@@ -3230,8 +3350,26 @@ static void ath12k_bss_assoc(struct ath1 + + ath12k_peer_assoc_prepare(ar, arvif, arsta, peer_arg, false); + ++ /* link_sta->he_cap must be protected by rcu_read_lock */ ++ ret = ath12k_mac_vif_recalc_sta_he_txbf(ar, arvif, &link_sta->he_cap, &hemode); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM: %d\n", ++ arvif->vdev_id, bss_conf->bssid, ret); ++ rcu_read_unlock(); ++ return; ++ } ++ + rcu_read_unlock(); + ++ /* keep this before ath12k_wmi_send_peer_assoc_cmd() */ ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ WMI_VDEV_PARAM_SET_HEMU_MODE, hemode); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n", ++ hemode, ret); ++ return; ++ } ++ + ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg); + if (ret) { + ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n", +@@ -3850,6 +3988,13 @@ static void ath12k_mac_bss_info_changed( + ether_addr_copy(arvif->bssid, info->bssid); + + if (changed & BSS_CHANGED_BEACON_ENABLED) { ++ if (info->enable_beacon) { ++ ret = ath12k_mac_set_he_txbf_conf(arvif); ++ if (ret) ++ ath12k_warn(ar->ab, ++ "failed to set HE TXBF config for vdev: %d\n", ++ arvif->vdev_id); ++ } + ath12k_control_beaconing(arvif, info); + + if (arvif->is_up && info->he_support && +@@ -7151,11 +7296,14 @@ static void ath12k_mac_copy_he_cap(struc + + he_cap_elem->mac_cap_info[1] &= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; +- ++ he_cap_elem->phy_cap_info[0] &= ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; ++ he_cap_elem->phy_cap_info[0] &= ++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; + he_cap_elem->phy_cap_info[5] &= + ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; +- he_cap_elem->phy_cap_info[5] &= +- ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK; + he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1; + + switch (iftype) { +@@ -8454,72 +8602,6 @@ static int ath12k_mac_setup_vdev_create_ + return 0; + } + +-static u32 +-ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype) +-{ +- struct ath12k_pdev_cap *pdev_cap = &pdev->cap; +- struct ath12k_band_cap *cap_band = NULL; +- u32 *hecap_phy_ptr = NULL; +- u32 hemode; +- +- if (pdev->cap.supported_bands & WMI_HOST_WLAN_2GHZ_CAP) +- cap_band = &pdev_cap->band[NL80211_BAND_2GHZ]; +- else +- cap_band = &pdev_cap->band[NL80211_BAND_5GHZ]; +- +- hecap_phy_ptr = &cap_band->he_cap_phy_info[0]; +- +- hemode = u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE) | +- u32_encode_bits(HECAP_PHY_SUBFMR_GET(hecap_phy_ptr), +- HE_MODE_SU_TX_BFER) | +- u32_encode_bits(HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr), +- HE_MODE_UL_MUMIMO); +- +- /* TODO: WDS and other modes */ +- if (viftype == NL80211_IFTYPE_AP) { +- hemode |= u32_encode_bits(HECAP_PHY_MUBFMR_GET(hecap_phy_ptr), +- HE_MODE_MU_TX_BFER) | +- u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) | +- u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA); +- } else { +- hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE); +- } +- +- return hemode; +-} +- +-static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar, +- struct ath12k_link_vif *arvif) +-{ +- u32 param_id, param_value; +- struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *ahvif = arvif->ahvif; +- int ret; +- +- param_id = WMI_VDEV_PARAM_SET_HEMU_MODE; +- param_value = ath12k_mac_prepare_he_mode(ar->pdev, ahvif->vif->type); +- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, param_value); +- if (ret) { +- ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n", +- arvif->vdev_id, ret, param_value); +- return ret; +- } +- param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; +- param_value = +- u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) | +- u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE, +- HE_TRIG_NONTRIG_SOUNDING_MODE); +- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, param_value); +- if (ret) { +- ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d\n", +- arvif->vdev_id, ret); +- return ret; +- } +- return ret; +-} +- + static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif) + { + struct ath12k_vif *ahvif = arvif->ahvif; +@@ -9706,14 +9788,6 @@ ath12k_mac_vdev_start_restart(struct ath + spin_unlock_bh(&ab->base_lock); + + /* TODO: Notify if secondary 80Mhz also needs radar detection */ +- if (link_conf->he_support) { +- ret = ath12k_set_he_mu_sounding_mode(ar, arvif); +- if (ret) { +- ath12k_warn(ar->ab, "failed to set he mode vdev %i\n", +- arg.vdev_id); +- return ret; +- } +- } + } + + arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -56,6 +56,21 @@ struct ath12k_generic_iter { + + #define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2 + ++#define HECAP_PHY_SUBFMR_GET(hecap_phy) \ ++ u8_get_bits(hecap_phy[3], IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) ++ ++#define HECAP_PHY_SUBFME_GET(hecap_phy) \ ++ u8_get_bits(hecap_phy[4], IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE) ++ ++#define HECAP_PHY_MUBFMR_GET(hecap_phy) \ ++ u8_get_bits(hecap_phy[4], IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER) ++ ++#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \ ++ u8_get_bits(hecap_phy[2], IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO) ++ ++#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \ ++ u8_get_bits(hecap_phy[2], IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO) ++ + enum ath12k_supported_bw { + ATH12K_BW_20 = 0, + ATH12K_BW_40 = 1, +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3131,31 +3131,6 @@ struct ath12k_wmi_rx_reorder_queue_remov + #define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2) + #define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3) + +-#define HECAP_PHYDWORD_0 0 +-#define HECAP_PHYDWORD_1 1 +-#define HECAP_PHYDWORD_2 2 +- +-#define HECAP_PHY_SU_BFER BIT(31) +-#define HECAP_PHY_SU_BFEE BIT(0) +-#define HECAP_PHY_MU_BFER BIT(1) +-#define HECAP_PHY_UL_MUMIMO BIT(22) +-#define HECAP_PHY_UL_MUOFDMA BIT(23) +- +-#define HECAP_PHY_SUBFMR_GET(hecap_phy) \ +- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_SU_BFER) +- +-#define HECAP_PHY_SUBFME_GET(hecap_phy) \ +- u32_get_bits(hecap_phy[HECAP_PHYDWORD_1], HECAP_PHY_SU_BFEE) +- +-#define HECAP_PHY_MUBFMR_GET(hecap_phy) \ +- u32_get_bits(hecap_phy[HECAP_PHYDWORD_1], HECAP_PHY_MU_BFER) +- +-#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \ +- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_UL_MUMIMO) +- +-#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \ +- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_UL_MUOFDMA) +- + #define HE_MODE_SU_TX_BFEE BIT(0) + #define HE_MODE_SU_TX_BFER BIT(1) + #define HE_MODE_MU_TX_BFEE BIT(2) +@@ -3167,8 +3142,11 @@ struct ath12k_wmi_rx_reorder_queue_remov + #define HE_DL_MUOFDMA_ENABLE 1 + #define HE_UL_MUOFDMA_ENABLE 1 + #define HE_DL_MUMIMO_ENABLE 1 ++#define HE_UL_MUMIMO_ENABLE 1 + #define HE_MU_BFEE_ENABLE 1 + #define HE_SU_BFEE_ENABLE 1 ++#define HE_MU_BFER_ENABLE 1 ++#define HE_SU_BFER_ENABLE 1 + + #define HE_VHT_SOUNDING_MODE_ENABLE 1 + #define HE_SU_MU_SOUNDING_MODE_ENABLE 1 diff --git a/patches/ath12k/104-2-wifi-ath12k-push-EHT-MU-MIMO-params-to-hardware.patch b/patches/ath12k/104-2-wifi-ath12k-push-EHT-MU-MIMO-params-to-hardware.patch new file mode 100644 index 0000000..d11e94f --- /dev/null +++ b/patches/ath12k/104-2-wifi-ath12k-push-EHT-MU-MIMO-params-to-hardware.patch @@ -0,0 +1,242 @@ +From patchwork Wed May 21 22:45:32 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096119 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id 697B71A23AA + for ; Wed, 21 May 2025 22:45:58 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867560; cv=none; + b=XceXZ7CY2+FEzM9RuC10/cGW+vmyB2cX8QWJ3ckav7jiY5NYBQe1XW2asWcHaAEmOwdUh2iRT6imeiQLYue78g4UAcBErvihTGqlYL0m+10CQMNHmQZurUQkLPeFS0WAwlA+HBgcdp+Z71PhXs/ttQD6dF/8mlPaeGqxlTUoEcM= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867560; c=relaxed/simple; + bh=mXjCwVOeMuqCjiNDATjkwHPrwNjm6Uv3d5yO5+bqbfk=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=SeDDAI+0lqXCMqhleIhxgpdPq9QuWaPI9jj0JOqYiwOIVtAsNqQv7KQ+AMvXDQTsIe0LfA2l23stlXB7sLNpKHTM9JhPsLkafU7mvBaiwTxaJR5tEi4zGQZhsrKSn/awYszamnM81hQS3r9bBgS4oe8AeFV2/lDXYPXNHCGv0+w= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=DwzHO5rL; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="DwzHO5rL" +Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LJflLg012749; + Wed, 21 May 2025 22:45:53 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + tiHJ0bp145D1K0TKBussv+a5p9S+5sP37NuNrmk03fg=; b=DwzHO5rLl1Vp87qm + lpxifM2nR9pLT0mgMqz/HRb/yTHCnS9oGDXzc24mnve2I/O9X/YT8q8qN+wjBlLB + 4W7snIItVpffzrSmAJupTNtzj8qbmIYeti1zUlDdVoesUaICbdiDvSeCWPUtfeaz + tNKDOmBUTvCb+1qxxciQZhuRobmmkuRgcg8VkgCFP+OyG5o1OrUESYu3QeZ62Hle + ODt78jw+qe8cE9e2TxGEZhy++loik0tbF8D9P3cX5L+CdB+i4TyWnFxwvNgJciIx + RptE1lyB75UdrnAqETq0km4svwyidUuum/x0hqd6TvlDod3b7FD4tjbE7EP5iQ5V + Dw2tXA== +Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf9carr-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:53 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjqtS008810 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:52 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:52 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Muna Sinada , + "Jeff + Johnson" +Subject: [PATCH ath-next V14 2/9] wifi: ath12k: push EHT MU-MIMO params to + hardware +Date: Wed, 21 May 2025 15:45:32 -0700 +Message-ID: <20250521224539.355985-3-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-ORIG-GUID: _eaDrXLa14UhDtRJT-hk8Y6z1fwFI6QB +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNSBTYWx0ZWRfX7QgTyyXEHZM8 + OnUvphQD/4J77Z8iHm4hJQIe6duMI5HbpiWELH5aRxqU7pFuvCjmltcmWPjwls9DzTkJnDGHMjo + FuBarQpMaZO8eQsx97aM8WpE0dpJHROE1ZRZ3SV8VEoTHHG712fvPw+oUWaZo6WccaEbxH9x9+W + n76tkFOOopbjRgOBmCokHCrfZmCMKcT4FLUFoiIDn0Fv8b/WKaut3Z+1hrEwcOuXCJv4X1QIOcx + 6NCnxNr8y1O1cwqXg3pBhHB+BpcLiEat6TlD9bH/5oUZHFce4W1jkZYs2J5VJnzLDeQxq8xBhP0 + Qal3bpuUPyWAMKZKH/uAEXwEZ5ZMghUioGuc78EBMJhSXa2VsT3lhmJtc/CaHDqNKFrp01I/KAh + 7UcIN/PKb8qOKrHE8/8cpuHgoBgB24X84Qo5rORKfnW4s7FbS0xkcs2ZV2TI0AIGz4eEZAOY +X-Authority-Analysis: v=2.4 cv=GawXnRXL c=1 sm=1 tr=0 ts=682e57a1 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=uoU_VXRAPQDrZd00miQA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-GUID: _eaDrXLa14UhDtRJT-hk8Y6z1fwFI6QB +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + mlxscore=0 mlxlogscore=999 lowpriorityscore=0 impostorscore=0 + priorityscore=1501 clxscore=1015 malwarescore=0 phishscore=0 bulkscore=0 + spamscore=0 suspectscore=0 adultscore=0 classifier=spam authscore=0 + authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 + engine=8.19.0-2505160000 definitions=main-2505210225 + +Currently, only the EHT IE in management frames is updated with +respect to MU-MIMO configurations, but this change is not +reflected in the hardware. Add support to propagate MU-MIMO +configurations to the hardware as well for AP mode. Similar +support for STA mode will be added in future. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Muna Sinada +Signed-off-by: Muna Sinada +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/mac.c | 58 +++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 21 ++++++++++ + 2 files changed, 79 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3292,6 +3292,58 @@ static int ath12k_mac_vif_recalc_sta_he_ + return 0; + } + ++static int ath12k_mac_set_eht_txbf_conf(struct ath12k_link_vif *arvif) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k *ar = arvif->ar; ++ u32 param = WMI_VDEV_PARAM_SET_EHT_MU_MODE; ++ u32 value = 0; ++ int ret; ++ struct ieee80211_bss_conf *link_conf; ++ ++ link_conf = ath12k_mac_get_link_bss_conf(arvif); ++ if (!link_conf) { ++ ath12k_warn(ar->ab, "unable to access bss link conf in eht txbf conf\n"); ++ return -ENOENT; ++ } ++ ++ if (!link_conf->eht_support) ++ return 0; ++ ++ if (link_conf->eht_su_beamformer) { ++ value |= u32_encode_bits(EHT_SU_BFER_ENABLE, EHT_MODE_SU_TX_BFER); ++ if (link_conf->eht_mu_beamformer && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ value |= u32_encode_bits(EHT_MU_BFER_ENABLE, ++ EHT_MODE_MU_TX_BFER) | ++ u32_encode_bits(EHT_DL_MUOFDMA_ENABLE, ++ EHT_MODE_DL_OFDMA_MUMIMO) | ++ u32_encode_bits(EHT_UL_MUOFDMA_ENABLE, ++ EHT_MODE_UL_OFDMA_MUMIMO); ++ } ++ ++ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) { ++ value |= u32_encode_bits(EHT_DL_MUOFDMA_ENABLE, EHT_MODE_DL_OFDMA) | ++ u32_encode_bits(EHT_UL_MUOFDMA_ENABLE, EHT_MODE_UL_OFDMA); ++ ++ if (link_conf->eht_80mhz_full_bw_ul_mumimo) ++ value |= u32_encode_bits(EHT_UL_MUMIMO_ENABLE, EHT_MODE_MUMIMO); ++ ++ if (link_conf->eht_su_beamformee) ++ value |= u32_encode_bits(EHT_SU_BFEE_ENABLE, ++ EHT_MODE_SU_TX_BFEE); ++ } ++ ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set vdev %d EHT MU mode: %d\n", ++ arvif->vdev_id, ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static void ath12k_bss_assoc(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *bss_conf) +@@ -3994,6 +4046,12 @@ static void ath12k_mac_bss_info_changed( + ath12k_warn(ar->ab, + "failed to set HE TXBF config for vdev: %d\n", + arvif->vdev_id); ++ ++ ret = ath12k_mac_set_eht_txbf_conf(arvif); ++ if (ret) ++ ath12k_warn(ar->ab, ++ "failed to set EHT TXBF config for vdev: %d\n", ++ arvif->vdev_id); + } + ath12k_control_beaconing(arvif, info); + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1176,6 +1176,7 @@ enum wmi_tlv_vdev_param { + WMI_VDEV_PARAM_BSS_COLOR, + WMI_VDEV_PARAM_SET_HEMU_MODE, + WMI_VDEV_PARAM_HEOPS_0_31 = 0x8003, ++ WMI_VDEV_PARAM_SET_EHT_MU_MODE = 0x8005, + }; + + enum wmi_tlv_peer_flags { +@@ -3148,6 +3149,26 @@ struct ath12k_wmi_rx_reorder_queue_remov + #define HE_MU_BFER_ENABLE 1 + #define HE_SU_BFER_ENABLE 1 + ++#define EHT_MODE_SU_TX_BFEE BIT(0) ++#define EHT_MODE_SU_TX_BFER BIT(1) ++#define EHT_MODE_MU_TX_BFEE BIT(2) ++#define EHT_MODE_MU_TX_BFER BIT(3) ++#define EHT_MODE_DL_OFDMA BIT(4) ++#define EHT_MODE_UL_OFDMA BIT(5) ++#define EHT_MODE_MUMIMO BIT(6) ++#define EHT_MODE_DL_OFDMA_TXBF BIT(7) ++#define EHT_MODE_DL_OFDMA_MUMIMO BIT(8) ++#define EHT_MODE_UL_OFDMA_MUMIMO BIT(9) ++ ++#define EHT_DL_MUOFDMA_ENABLE 1 ++#define EHT_UL_MUOFDMA_ENABLE 1 ++#define EHT_DL_MUMIMO_ENABLE 1 ++#define EHT_UL_MUMIMO_ENABLE 1 ++#define EHT_MU_BFEE_ENABLE 1 ++#define EHT_SU_BFEE_ENABLE 1 ++#define EHT_MU_BFER_ENABLE 1 ++#define EHT_SU_BFER_ENABLE 1 ++ + #define HE_VHT_SOUNDING_MODE_ENABLE 1 + #define HE_SU_MU_SOUNDING_MODE_ENABLE 1 + #define HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE 1 diff --git a/patches/ath12k/104-3-wifi-ath12k-move-HE-MCS-mapper-to-a-separate-function.patch b/patches/ath12k/104-3-wifi-ath12k-move-HE-MCS-mapper-to-a-separate-function.patch new file mode 100644 index 0000000..bf72cef --- /dev/null +++ b/patches/ath12k/104-3-wifi-ath12k-move-HE-MCS-mapper-to-a-separate-function.patch @@ -0,0 +1,173 @@ +From patchwork Wed May 21 22:45:33 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096126 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com + [205.220.168.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4E00239570 + for ; Wed, 21 May 2025 22:46:01 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.168.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867563; cv=none; + b=m0NU8tyG2d1pHiYNjTYhCTeGXC0pFtHNZTKxb+dc5AEzzUCa75lxPxtYFZApv1QHaLqo3lGkZ+ADhqhj/V82GA+bUeetm3hSsnyGgjbayU3IzqeO09+VPkt9sx9hdrTMlVGEI4c5881Zho41rlVW65O/SlmqRi4J/ajQzA4tiGQ= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867563; c=relaxed/simple; + bh=0bTV82dMwisd7nmbtolnSKswG/aTjqN0YxpAx66Oqv8=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=jOkezej/N9fmvOtPNCGPpnPNtoQ+pAG4k1zAiw3xnL1iikk7VcJlbXDCrGUithxMZE2513zz/fsfDjXx0AMi4YT1ISljvGCw9B0dGQ5ECiFfoGLc+12nnsvqjiXI5zla6C1iX7bgtJjv/OYWzoY0TR5jI28CZWC/Pa9fT/X0duw= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=UqUMYAcW; arc=none smtp.client-ip=205.220.168.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="UqUMYAcW" +Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LIDlKw013406; + Wed, 21 May 2025 22:45:53 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + tYXOeicncMlFjsw5kmnB5kxC/Nrj/HibF1jgO4m8lhM=; b=UqUMYAcWWQ07Z79h + GESSroshxr6zIUBw3jr/ESGDCO554RYWZZh9PXJxjTRM3ceCrNHNpCAT+mqXXiWy + eb+l7G0W+s1l/MStBq7B43CSdKxljZtlkC/JsHk6DQjBacQzVB8qAiq3ShbR/vn7 + ud3kzjHtYsfLvIpi+8wLTkE1in8E/CUFZ4bea866xldnrcOVEa7EuxKwKXj3sLhE + 8n3IsPUIYGLKnEFkmWFZTXTqlEOV9lVYdTxeDAUBxII8PQIKu+dlB/UWffTFTSOd + aQDPK5N6y8x29E2fugyy2XBSEFskz50Jb60+kJhHFGTgl5cQw+NfymuC9SQJBWaE + HFZu+w== +Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwh5cfg1-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:53 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjqn9020293 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:52 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:52 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Muna Sinada , + "Jeff + Johnson" +Subject: [PATCH ath-next V14 3/9] wifi: ath12k: move HE MCS mapper to a + separate function +Date: Wed, 21 May 2025 15:45:33 -0700 +Message-ID: <20250521224539.355985-4-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX0c42ymLt+PTP + 1OuRw1LMafhFmBy7Y+zhs50WttVxoryUfqamicOcfcFB1N0ReYFgzeQ7geC/w54E8E6mzQDYeie + WWkPGvuIyvtCjzhBcBwz1A7W/LdsI7Od6+VlXyCuAp4pbCASB7kqVnI7Neak6mvdIQIW5khVLX7 + r/364Kop8/BPQzOVUZf5snfx4TBCgWauiHZQBTJupIn1Tf8+NctUXB8H3QNfu8zJTLVrBA3rtt1 + +yjeNOHom4U/t0u5Vzxu+8XctXsWHoYytfluXbsRo7WNut0MwPSY8GCm7RQ2wDQp0CzdactGb6t + KCMvNcpkDRjEtOdkNtf2BeVHF1yJKxuibe6qssobLjTadJRkC33xnz5E+hzF6sEZlg7JWok01h4 + OxWFUldQYnF/eQjZYTQcgLyH91h9gWkvz0YJWKGCrg0PlxqeIFS/SQvVNs7qMnsX0qrXb7NV +X-Authority-Analysis: v=2.4 cv=XeWJzJ55 c=1 sm=1 tr=0 ts=682e57a1 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=4Pgy4kl5F6fn7-PMLAkA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-GUID: CVZHk1FyIP3eCYHbVaXVp1fjSAGIjnVJ +X-Proofpoint-ORIG-GUID: CVZHk1FyIP3eCYHbVaXVp1fjSAGIjnVJ +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + phishscore=0 clxscore=1015 mlxlogscore=999 mlxscore=0 bulkscore=0 spamscore=0 + suspectscore=0 impostorscore=0 adultscore=0 malwarescore=0 lowpriorityscore=0 + priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc= + route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 + definitions=main-2505210226 + +Refactor the HE MCS mapper functionality in +ath12k_mac_copy_he_cap() into a new function. + +This helps improve readability, extensibility and will be used +when adding support for 160 MHz bandwidth in subsequent patches. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Muna Sinada +Signed-off-by: Muna Sinada +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7339,12 +7339,24 @@ static __le16 ath12k_mac_setup_he_6ghz_c + return cpu_to_le16(bcap->he_6ghz_capa); + } + ++static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap, ++ struct ieee80211_sta_he_cap *he_cap) ++{ ++ struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp; ++ ++ mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); ++ mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); ++ mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++} ++ + static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap, + int iftype, u8 num_tx_chains, + struct ieee80211_sta_he_cap *he_cap) + { + struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; +- struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp; + + he_cap->has_he = true; + memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info, +@@ -7384,13 +7396,7 @@ static void ath12k_mac_copy_he_cap(struc + break; + } + +- mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); +- mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); +- mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- ++ ath12k_mac_set_hemcsmap(band_cap, he_cap); + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + if (he_cap_elem->phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) diff --git a/patches/ath12k/104-4-wifi-ath12k-generate-rx-and-tx-mcs-maps-for-supported-HE-mcs.patch b/patches/ath12k/104-4-wifi-ath12k-generate-rx-and-tx-mcs-maps-for-supported-HE-mcs.patch new file mode 100644 index 0000000..d85077a --- /dev/null +++ b/patches/ath12k/104-4-wifi-ath12k-generate-rx-and-tx-mcs-maps-for-supported-HE-mcs.patch @@ -0,0 +1,197 @@ +From patchwork Wed May 21 22:45:34 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096123 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3C04239581 + for ; Wed, 21 May 2025 22:45:57 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867561; cv=none; + b=JUfYB6YNOea3E6luldlHf63eW7OUVXEtawJXGCeH7nt9iIJpG0ODfz3v+Zl+gtQtUZ1ELh/UAhCubbThHH30w661eEN5+cQarbiqdd1cN5dnkAsmZUNSD6l//QpurFV6Wsvv4Nr2fYgyuAVHf9JDoITZKNEbIki68J7WTV+fieU= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867561; c=relaxed/simple; + bh=e6/wBkUC5dKwNLeEqNLmC/3pJt4EcGfxZRx+zntD5Ek=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=bg3Y4gdyPqhSKZtqqeN+SjMvTgg+BVUsyqAvkS3YPjV+C7dPwxcByNFjDRsuBqwHuSvgolo2ISExqyfJkgT6Flp4H+hriFJHcMdI0WmDf9NrBPI+E07JvNLDvP5X59C6pSrqpjXYngUV6AvPCJL7ynVBFF80h0neCm0IRu8Ur8w= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=LbIprPEi; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="LbIprPEi" +Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LIdAVE024983; + Wed, 21 May 2025 22:45:54 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + oR9JZ4DE7PwiZ/DcP72BpK9yTZspsBeRbWSrP3w24nY=; b=LbIprPEif55TZs6Z + ZsvTaIhFDxESbkxn/avX548dzh51JY3wFWHowpcPEnJJdIE1oNPWkxrPo0hHkyUb + UICPtIHoZHdMwN/uHPyglzBnBLNP82LGLHZI5eHx6jVz4INyCFm1Gmof8YNLLIo/ + pTKj4Qx3OO0jH6zSnAoKIIg39v5TWetjVZbL2qbNR+GImD0RtoefBQxRgyJWn11r + O3ycFAW9xlW8wYJql07vue+hM3MWNtk5EPqF70c7JrrmMAYvTyOFuP0Kaf11szIB + mF4bMyb+bb1/QA6moW7LDIoDBWEjCLINcTdGUPTnwnfBWlxZJhZoMqzU9ZuZgvsR + 1UjthA== +Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf4vc5x-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:54 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjrWL023291 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:53 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:52 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Muna Sinada , + "Jeff + Johnson" +Subject: [PATCH ath-next V14 4/9] wifi: ath12k: generate rx and tx mcs maps + for supported HE mcs +Date: Wed, 21 May 2025 15:45:34 -0700 +Message-ID: <20250521224539.355985-5-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-GUID: mYgnUwiU6CWGXCKmK4mo491eQG1yf62Y +X-Proofpoint-ORIG-GUID: mYgnUwiU6CWGXCKmK4mo491eQG1yf62Y +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX1nkoUF8smaXX + IWIOVUfe7hMPdAVBJy7J1imFvumQnVaEdoZ98Hgv5FTjeK2Ebgl2R2fohvg1z4LsyCLnU8qfg96 + 1OdC0+PM8u7DhRIEnk7H2EZt0UJoJRxlc7daiIvimTjbBLu53yfgzses5Gth0zLCzoih5ffW/H5 + 1h2tf1ZE4W6AmHjQJc+WE0P3RhBMdl286VT/kc0ko03He0+5/QdxsynqL2e4svB4f3035pzXOEK + dUS4nBFSZJXuBkq0d//SizRJgH9egq51A/OVPm8om04qEcOK3x9OmrrborAen5I0iuLaqAMMBXa + nlUKQ4fpPRovjAByevo6BIIwB698Nmo72bZcFiWOocONR92lAssB6pFXJnuwOC6VQ7MJE7DKc0x + 5UnlyGSMzMAM7cQXuGFk1AK16e6Tu/rC5YA6A4ogDKajrcBGepxGFKcZ+xK4+BwuwgI4Qysv +X-Authority-Analysis: v=2.4 cv=R7UDGcRX c=1 sm=1 tr=0 ts=682e57a2 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=WmtfbAKxhnfIJFSrnnQA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + phishscore=0 clxscore=1015 mlxlogscore=999 priorityscore=1501 spamscore=0 + bulkscore=0 lowpriorityscore=0 malwarescore=0 suspectscore=0 mlxscore=0 + impostorscore=0 adultscore=0 classifier=spam authscore=0 authtc=n/a authcc= + route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 + definitions=main-2505210226 + +Generate rx and tx mcs maps in ath12k_mac_set_hemcsmap() based +on number of supported tx/rx chains and set them in supported +mcs/nss for HE capabilities. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Muna Sinada +Signed-off-by: Muna Sinada +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/mac.c | 40 ++++++++++++++++++++------- + 1 file changed, 30 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7339,20 +7339,40 @@ static __le16 ath12k_mac_setup_he_6ghz_c + return cpu_to_le16(bcap->he_6ghz_capa); + } + +-static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap, ++static void ath12k_mac_set_hemcsmap(struct ath12k *ar, ++ struct ath12k_pdev_cap *cap, + struct ieee80211_sta_he_cap *he_cap) + { + struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp; ++ u16 txmcs_map, rxmcs_map; ++ u32 i; + +- mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); +- mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); +- mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ rxmcs_map = 0; ++ txmcs_map = 0; ++ for (i = 0; i < 8; i++) { ++ if (i < ar->num_tx_chains && ++ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ ++ if (i < ar->num_rx_chains && ++ (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ } ++ ++ mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff); ++ mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff); ++ mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff); ++ mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff); ++ mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff); ++ mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff); + } + +-static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap, ++static void ath12k_mac_copy_he_cap(struct ath12k *ar, ++ struct ath12k_band_cap *band_cap, + int iftype, u8 num_tx_chains, + struct ieee80211_sta_he_cap *he_cap) + { +@@ -7396,7 +7416,7 @@ static void ath12k_mac_copy_he_cap(struc + break; + } + +- ath12k_mac_set_hemcsmap(band_cap, he_cap); ++ ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap); + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + if (he_cap_elem->phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) +@@ -7586,7 +7606,7 @@ static int ath12k_mac_copy_sband_iftype_ + + data[idx].types_mask = BIT(i); + +- ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap); ++ ath12k_mac_copy_he_cap(ar, band_cap, i, ar->num_tx_chains, he_cap); + if (band == NL80211_BAND_6GHZ) { + data[idx].he_6ghz_capa.capa = + ath12k_mac_setup_he_6ghz_cap(cap, band_cap); diff --git a/patches/ath12k/104-5-wifi-ath12k-fix-TX-and-RX-MCS-rate-configurations-in-HE-mode.patch b/patches/ath12k/104-5-wifi-ath12k-fix-TX-and-RX-MCS-rate-configurations-in-HE-mode.patch new file mode 100644 index 0000000..49ef320 --- /dev/null +++ b/patches/ath12k/104-5-wifi-ath12k-fix-TX-and-RX-MCS-rate-configurations-in-HE-mode.patch @@ -0,0 +1,152 @@ +From patchwork Wed May 21 22:45:35 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096120 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3B9F239570 + for ; Wed, 21 May 2025 22:45:57 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867560; cv=none; + b=GmlOnDZdpnT/77kfeg7qPbZIn+pp+Rv41/WYnHylPZroDHwpWp5rzjObHMVoVIVB8f5dpHJSWNb5ucf0EdCqAqynnnDnAHne0d3j8kMBBH6ZVQr4AnIsYhkIrbmy6o7JffEBF094XVxGwQTjyWSEPi6VY94Md6L1NnuF0J5lJXw= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867560; c=relaxed/simple; + bh=Xdsuttpv57eTzMnRm7g3A0+frkCx/SnGj1xOjVOXHng=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=DCZ4pyonUsAaIuBQUBu/1NYBINM2V/yqfV+6ngHC6I8x7PP5e0WLPB1zEyJgRG752GtXxlhP3WdI6a+eW/8O0I64lNeSLtCeGZQ2ljn0mAfcuMtjB3rZq3UejFTR8v3I78Chfhv8/eSjfW7gSO+sswpSCXiFykPgseD3Hhz6W/4= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=n5c8p9dB; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="n5c8p9dB" +Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LIhKMc027654; + Wed, 21 May 2025 22:45:54 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + igBIHxXxEIGErFGPWQKC8rBeF0DUPvb+tsDy6dmbEUQ=; b=n5c8p9dBo/+917ae + iUuuRoUPhgwmxRjEorR4N5thttRSLen0XwHulOSFzfVHZvX/ZX7Xb8qa67RpJUAw + jx3TGu38TFybZ9zCbXxa3PoR7FqIyl7TyaU+RpGmjLnDTRjq5ODiDDkcGM8aLJ6C + pgH1JDyjAtZODpP3W+kKpoMlU/N8QCB8wVOob4E3+nH0XDeYWh0cSY4dAnFcFYsC + dgkUoVt65T3wJptGX80bBT1muPG/3O+IiWrYoP6NVayscmgOnCqKVpuSjYrEn/02 + HlxMp7yg/I4LhlQquL2SfmAXdKThQLrOF/XiFsCW2VZETvSbXsLI0NXYRbRFUxC4 + e9SLmw== +Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf9cars-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:54 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjrc1023294 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:53 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:53 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Jeff Johnson +Subject: [PATCH ath-next V14 5/9] wifi: ath12k: fix TX and RX MCS rate + configurations in HE mode +Date: Wed, 21 May 2025 15:45:35 -0700 +Message-ID: <20250521224539.355985-6-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-ORIG-GUID: lrtwH7rWiPRFD03fbbD0IavLBLpNgTW- +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNSBTYWx0ZWRfX0HS2wunF/V5Q + jQqxwakF2Imrc/4a4WgPSFOFxUyO27D7Yw6gnIBRodgtwOFgflHDfeJMrELW79jrSDvXvRC0nnc + lTonRisd7/CZWExy3sM2diYhHrZ5YT1dPhFtq33ItpY8BaOhwiLxc3wn0tlWRX8B/cd+xyEHTZY + A4nCDSw77SEdaZfmqAB81LMzQWIuTucnxkms4pM1CIIYZrgAPcBk4XN8tWVQ6JQKCpMpelTF6Hj + /XLCY2ByRqjtwd/zSjtcCfLOyKdT+uQtAJU1XZvedwqQW5MFk2GeD7O72PfhAP1V0YcbHdiTxde + roRpAlQg48k0Ug5EMIUPb9TYEP15vwtPDTw03C3u7eOhs6znDqvMYNAtXwbxfGeHRwjsbMgpWLG + +weN3zziLWlwb66N0xo5nfdJRHrOVDNcSx8/Z/xvCmHBTuVr44Q7It0iW+CGbHNqXrg4h4CH +X-Authority-Analysis: v=2.4 cv=GawXnRXL c=1 sm=1 tr=0 ts=682e57a2 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=mu3tZSmwaZwQUXtd2tAA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-GUID: lrtwH7rWiPRFD03fbbD0IavLBLpNgTW- +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + mlxscore=0 mlxlogscore=999 lowpriorityscore=0 impostorscore=0 + priorityscore=1501 clxscore=1015 malwarescore=0 phishscore=0 bulkscore=0 + spamscore=0 suspectscore=0 adultscore=0 classifier=spam authscore=0 + authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 + engine=8.19.0-2505160000 definitions=main-2505210225 + +Currently, the TX and RX MCS rate configurations per peer are +reversed when sent to the firmware. As a result, RX MCS rates +are configured for TX, and vice versa. This commit rectifies +the configuration to match what the firmware expects. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/wmi.c | 4 ++-- + drivers/net/wireless/ath/ath12k/wmi.h | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2333,8 +2333,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + he_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET, + sizeof(*he_mcs)); + +- he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]); +- he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]); ++ he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]); ++ he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]); + ptr += sizeof(*he_mcs); + } + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -4157,7 +4157,9 @@ struct ath12k_wmi_vht_rate_set_params { + + struct ath12k_wmi_he_rate_set_params { + __le32 tlv_header; ++ /* MCS at which the peer can receive */ + __le32 rx_mcs_set; ++ /* MCS at which the peer can transmit */ + __le32 tx_mcs_set; + } __packed; + diff --git a/patches/ath12k/104-6-wifi-ath12k-add-support-for-setting-fixed-HE-rate-GI-LTF.patch b/patches/ath12k/104-6-wifi-ath12k-add-support-for-setting-fixed-HE-rate-GI-LTF.patch new file mode 100644 index 0000000..b7ad233 --- /dev/null +++ b/patches/ath12k/104-6-wifi-ath12k-add-support-for-setting-fixed-HE-rate-GI-LTF.patch @@ -0,0 +1,1184 @@ +From patchwork Wed May 21 22:45:36 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096125 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A17F1B0F20 + for ; Wed, 21 May 2025 22:45:59 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867562; cv=none; + b=bEGfSmKJAIERqJyK0yJndcYM+a7cpfrIkMLoGUTFvAkrcwqnlh3F9AqLbcb8fKznhfaQKFVRUdpVGSjFaplFVSp20RuXvPC2NLb0eKZrz5qS/4geTMxY/BeWuVN+i3ouoQzfYz8Vq6sTqLE5d6b650cCVf8hpY+VZ3ZTNWxVvdA= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867562; c=relaxed/simple; + bh=hBxlXRYYCPbv8+evEatym1UfdpOfENFUVDWgibN+XTg=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=U32JKi6TAoRF/9e1cv0vPGUM6BaRhoFXM0b36j5PBpvKQmRXKDF/UNScd5EJnrFOPlgjPD7GOc+TdHqsFGk/7pNucA1++GU00SZ0q/223zg5dCsYLmfLrRu3G22WZS2hWuNKuUPFJEFFLEJ8UQWKtFB0oWsQcx+Oj1mWPbBrDU8= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=bzVTzUcl; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="bzVTzUcl" +Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LJiK6V032422; + Wed, 21 May 2025 22:45:55 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + cpcIGD4iPSOaZzDkHZpoGs5Kor0sF3EnocHYcBOazgM=; b=bzVTzUclt3RkLn9A + YI8+MC64RjF5llUqmQ0G53D8sAQZ+95fc92X/ZrZvnyr7X0FBI+gU05yKzNuv4M5 + XcIWK7Y8gjr55i9w18cWHGW2Q/JGC8pJlx0A/SEAMIMXeeEmgJqdKowT2wMjzIIH + wb7JmE9d6z6ZKcgQYx9KICXaaEFQ9uxyRyjlJMMEJ3zb7MjxZPCCGtCI31Aqczpk + B3X+1UgRT+OJzV6vIF0kdn/sjU69iZNHoPAUDYqInWCs2lPLMUO5mckhOG3fH8s6 + jmhgpwlpUYx18jawRUpklvujXfFiDV4daXLeUKzL5b08f5OcSRvd7+iOytudYgr0 + U9VYkw== +Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwfb4b3w-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:55 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjsC2027097 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:54 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:53 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Muna Sinada +Subject: [PATCH ath-next V14 6/9] wifi: ath12k: add support for setting fixed + HE rate/GI/LTF +Date: Wed, 21 May 2025 15:45:36 -0700 +Message-ID: <20250521224539.355985-7-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-ORIG-GUID: 7uuxK_kl_b0JzKZoWIyq_ZYKeKL3it15 +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX7sjoM15po0tB + FcR1nwzr8TocaDYnIXgl13rA+kjwsizlMt/N5cu8dCWo9YQKqFNy42Z2VEYmoDRw7dBnYnsMIL/ + wwv4hQYQslnxilRJaX/MVQ50/xxhSry8NrKA2QXvIg3btmiW4gQfrn3+k1Rm3o/gAGv2Yz4R8lw + YBPHVdQkgGJXYgsiB/b+copbnU621GYiYrCW6yUQHHIiwzjMljzzsk+9Koc6yeVByyPj86P80y7 + 2C8L1vuRAy8gCMSScMB9CyQ6+tLCKa1W2bhA0Oxz/+RGEXbujS4NDXCWz+EqIaYS5HXuD32pODy + O2wMURrbgE5PJIjjvpAdtqZL65QVaoVK1LWU6Co0NtHytEjuaZmr1hbb4hVDAtQio2Bw/K8yCM+ + ikcJ1sGkE78mu/U7gQjG6g0Z71Q/w13jBOz+RIocPFi2FyEjy5KDFmUBzY+jDCIRLi06R8sP +X-Proofpoint-GUID: 7uuxK_kl_b0JzKZoWIyq_ZYKeKL3it15 +X-Authority-Analysis: v=2.4 cv=dLCmmPZb c=1 sm=1 tr=0 ts=682e57a3 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=KygRlO7-s-l5tpycOzUA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + mlxscore=0 clxscore=1015 adultscore=0 bulkscore=0 phishscore=0 suspectscore=0 + impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0 + priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc= + route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 + definitions=main-2505210226 + +Add support to set fixed HE rate/GI/LTF values using nl80211. +Reuse parts of the existing code path already used for HT/VHT +to implement the new helpers symmetrically, similar to how +HT/VHT is handled. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Muna Sinada +Signed-off-by: Muna Sinada +Signed-off-by: Pradeep Kumar Chitrapu +--- + drivers/net/wireless/ath/ath12k/mac.c | 650 +++++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/wmi.h | 27 ++ + 2 files changed, 625 insertions(+), 52 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -521,6 +521,18 @@ ath12k_mac_max_vht_nss(const u16 *vht_mc + return 1; + } + ++static u32 ++ath12k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) ++{ ++ int nss; ++ ++ for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--) ++ if (he_mcs_mask[nss]) ++ return nss + 1; ++ ++ return 1; ++} ++ + static u8 ath12k_parse_mpdudensity(u8 mpdudensity) + { + /* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing": +@@ -2053,9 +2065,15 @@ static void ath12k_peer_assoc_h_ht(struc + arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG; + } + +- if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) { +- if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 | +- IEEE80211_HT_CAP_SGI_40)) ++ /* As firmware handles these two flags (IEEE80211_HT_CAP_SGI_20 ++ * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, reset both ++ * flags if guard interval is to force Long GI ++ */ ++ if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_FORCE_LGI) { ++ arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40); ++ } else { ++ /* Enable SGI flag if either SGI_20 or SGI_40 is supported */ ++ if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) + arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG; + } + +@@ -2178,11 +2196,12 @@ static void ath12k_peer_assoc_h_vht(stru + struct ieee80211_link_sta *link_sta; + struct cfg80211_chan_def def; + enum nl80211_band band; +- const u16 *vht_mcs_mask; ++ u16 *vht_mcs_mask; + u16 tx_mcs_map; + u8 ampdu_factor; + u8 max_nss, vht_mcs; +- int i; ++ int i, vht_nss, nss_idx; ++ bool user_rate_valid = true; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + +@@ -2235,6 +2254,25 @@ static void ath12k_peer_assoc_h_vht(stru + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) + arg->bw_160 = true; + ++ vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask); ++ ++ if (vht_nss > link_sta->rx_nss) { ++ user_rate_valid = false; ++ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { ++ if (vht_mcs_mask[nss_idx]) { ++ user_rate_valid = true; ++ break; ++ } ++ } ++ } ++ ++ if (!user_rate_valid) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "Setting vht range MCS value to peer supported nss:%d for peer %pM\n", ++ link_sta->rx_nss, arsta->addr); ++ vht_mcs_mask[link_sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; ++ } ++ + /* Calculate peer NSS capability from VHT capabilities if STA + * supports VHT. + */ +@@ -2274,6 +2312,72 @@ static void ath12k_peer_assoc_h_vht(stru + /* TODO: rxnss_override */ + } + ++static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss) ++{ ++ switch ((mcs_map >> (2 * nss)) & 0x3) { ++ case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1; ++ case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1; ++ case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1; ++ } ++ return 0; ++} ++ ++static u16 ath12k_peer_assoc_h_he_limit(u16 tx_mcs_set, ++ const u16 *he_mcs_limit) ++{ ++ int idx_limit; ++ int nss; ++ u16 mcs_map; ++ u16 mcs; ++ ++ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) { ++ mcs_map = ath12k_mac_get_max_he_mcs_map(tx_mcs_set, nss) & ++ he_mcs_limit[nss]; ++ ++ if (mcs_map) ++ idx_limit = fls(mcs_map) - 1; ++ else ++ idx_limit = -1; ++ ++ switch (idx_limit) { ++ case 0 ... 7: ++ mcs = IEEE80211_HE_MCS_SUPPORT_0_7; ++ break; ++ case 8: ++ case 9: ++ mcs = IEEE80211_HE_MCS_SUPPORT_0_9; ++ break; ++ case 10: ++ case 11: ++ mcs = IEEE80211_HE_MCS_SUPPORT_0_11; ++ break; ++ default: ++ WARN_ON(1); ++ fallthrough; ++ case -1: ++ mcs = IEEE80211_HE_MCS_NOT_SUPPORTED; ++ break; ++ } ++ ++ tx_mcs_set &= ~(0x3 << (nss * 2)); ++ tx_mcs_set |= mcs << (nss * 2); ++ } ++ ++ return tx_mcs_set; ++} ++ ++static bool ++ath12k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) ++{ ++ int nss; ++ ++ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) ++ if (he_mcs_mask[nss]) ++ return false; ++ ++ return true; ++} ++ + static void ath12k_peer_assoc_h_he(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, +@@ -2284,18 +2388,28 @@ static void ath12k_peer_assoc_h_he(struc + const struct ieee80211_sta_he_cap *he_cap; + struct ieee80211_bss_conf *link_conf; + struct ieee80211_link_sta *link_sta; ++ struct cfg80211_chan_def def; + int i; + u8 ampdu_factor, max_nss; + u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; + u8 rx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; + u16 mcs_160_map, mcs_80_map; ++ u8 link_id = arvif->link_id; + bool support_160; +- u16 v; ++ enum nl80211_band band; ++ u16 *he_mcs_mask; ++ u8 he_mcs; ++ u16 he_tx_mcs = 0, v = 0; ++ int he_nss, nss_idx; ++ bool user_rate_valid = true; ++ ++ if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def))) ++ return; + + link_conf = ath12k_mac_get_link_bss_conf(arvif); + if (!link_conf) { + ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc he for vif %pM link %u", +- vif->addr, arvif->link_id); ++ vif->addr, link_id); + return; + } + +@@ -2310,6 +2424,12 @@ static void ath12k_peer_assoc_h_he(struc + if (!he_cap->has_he) + return; + ++ band = def.chan->band; ++ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; ++ ++ if (ath12k_peer_assoc_h_he_masked(he_mcs_mask)) ++ return; ++ + arg->he_flag = true; + + support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] & +@@ -2415,25 +2535,47 @@ static void ath12k_peer_assoc_h_he(struc + if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ) + arg->twt_requester = true; + ++ he_nss = ath12k_mac_max_he_nss(he_mcs_mask); ++ ++ if (he_nss > link_sta->rx_nss) { ++ user_rate_valid = false; ++ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { ++ if (he_mcs_mask[nss_idx]) { ++ user_rate_valid = true; ++ break; ++ } ++ } ++ } ++ ++ if (!user_rate_valid) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "Setting he range MCS value to peer supported nss:%d for peer %pM\n", ++ link_sta->rx_nss, arsta->addr); ++ he_mcs_mask[link_sta->rx_nss - 1] = he_mcs_mask[he_nss - 1]; ++ } ++ + switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_160: + if (he_cap->he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) { +- v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80); ++ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask); + arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v; + + v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80); + arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v; + + arg->peer_he_mcs_count++; ++ he_tx_mcs = v; + } + v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); + arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v; + +- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160); ++ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask); + arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v; + + arg->peer_he_mcs_count++; ++ if (!he_tx_mcs) ++ he_tx_mcs = v; + fallthrough; + + default: +@@ -2441,11 +2583,36 @@ static void ath12k_peer_assoc_h_he(struc + arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v; + + v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80); ++ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask); + arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v; + + arg->peer_he_mcs_count++; ++ if (!he_tx_mcs) ++ he_tx_mcs = v; + break; + } ++ ++ /* Calculate peer NSS capability from HE capabilities if STA ++ * supports HE. ++ */ ++ for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) { ++ he_mcs = he_tx_mcs >> (2 * i) & 3; ++ ++ /* In case of fixed rates, MCS Range in he_tx_mcs might have ++ * unsupported range, with he_mcs_mask set, so check either of them ++ * to find nss. ++ */ ++ if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED || ++ he_mcs_mask[i]) ++ max_nss = i + 1; ++ } ++ ++ max_nss = min(max_nss, ar->num_tx_chains); ++ arg->peer_nss = min(link_sta->rx_nss, max_nss); ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac he peer %pM nss %d mcs cnt %d\n", ++ arsta->addr, arg->peer_nss, arg->peer_he_mcs_count); + } + + static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar, +@@ -2781,6 +2948,7 @@ static void ath12k_peer_assoc_h_phymode( + enum nl80211_band band; + const u8 *ht_mcs_mask; + const u16 *vht_mcs_mask; ++ const u16 *he_mcs_mask; + enum wmi_phy_mode phymode = MODE_UNKNOWN; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); +@@ -2794,6 +2962,7 @@ static void ath12k_peer_assoc_h_phymode( + band = def.chan->band; + ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs; + vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs; ++ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; + + link_sta = ath12k_mac_get_link_sta(arsta); + if (!link_sta) { +@@ -2809,7 +2978,8 @@ static void ath12k_peer_assoc_h_phymode( + phymode = MODE_11BE_EHT40_2G; + else + phymode = MODE_11BE_EHT20_2G; +- } else if (link_sta->he_cap.has_he) { ++ } else if (link_sta->he_cap.has_he && ++ !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + phymode = MODE_11AX_HE80_2G; + else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) +@@ -2839,7 +3009,8 @@ static void ath12k_peer_assoc_h_phymode( + /* Check EHT first */ + if (link_sta->eht_cap.has_eht) { + phymode = ath12k_mac_get_phymode_eht(ar, link_sta); +- } else if (link_sta->he_cap.has_he) { ++ } else if (link_sta->he_cap.has_he && ++ !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { + phymode = ath12k_mac_get_phymode_he(ar, link_sta); + } else if (link_sta->vht_cap.vht_supported && + !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { +@@ -3623,10 +3794,13 @@ static void ath12k_mac_init_arvif(struct + + for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) { + arvif->bitrate_mask.control[i].legacy = 0xffffffff; ++ arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; + memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff, + sizeof(arvif->bitrate_mask.control[i].ht_mcs)); + memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff, + sizeof(arvif->bitrate_mask.control[i].vht_mcs)); ++ memset(arvif->bitrate_mask.control[i].he_mcs, 0xff, ++ sizeof(arvif->bitrate_mask.control[i].he_mcs)); + } + + /* Handle MLO related assignments */ +@@ -5282,6 +5456,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(st + } + + static int ++ath12k_mac_bitrate_mask_num_he_rates(struct ath12k *ar, ++ enum nl80211_band band, ++ const struct cfg80211_bitrate_mask *mask) ++{ ++ int num_rates = 0; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) ++ num_rates += hweight16(mask->control[band].he_mcs[i]); ++ ++ return num_rates; ++} ++ ++static int + ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, + const struct cfg80211_bitrate_mask *mask, +@@ -5327,6 +5515,60 @@ ath12k_mac_set_peer_vht_fixed_rate(struc + return ret; + } + ++static int ++ath12k_mac_set_peer_he_fixed_rate(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, ++ const struct cfg80211_bitrate_mask *mask, ++ enum nl80211_band band) ++{ ++ struct ath12k *ar = arvif->ar; ++ u8 he_rate, nss; ++ u32 rate_code; ++ int ret, i; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ++ ++ sta = ath12k_ahsta_to_sta(ahsta); ++ nss = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) { ++ if (hweight16(mask->control[band].he_mcs[i]) == 1) { ++ nss = i + 1; ++ he_rate = ffs(mask->control[band].he_mcs[i]) - 1; ++ } ++ } ++ ++ if (!nss) { ++ ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM", ++ arsta->addr); ++ return -EINVAL; ++ } ++ ++ /* Avoid updating invalid nss as fixed rate*/ ++ if (nss > sta->deflink.rx_nss) ++ return -EINVAL; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates", ++ arsta->addr); ++ ++ rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1, ++ WMI_RATE_PREAMBLE_HE); ++ ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, ++ arvif->vdev_id, ++ WMI_PEER_PARAM_FIXED_RATE, ++ rate_code); ++ if (ret) ++ ath12k_warn(ar->ab, ++ "failed to update STA %pM Fixed Rate %d: %d\n", ++ arsta->addr, rate_code, ret); ++ ++ return ret; ++} ++ + static int ath12k_mac_station_assoc(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, +@@ -5339,7 +5581,7 @@ static int ath12k_mac_station_assoc(stru + struct cfg80211_chan_def def; + enum nl80211_band band; + struct cfg80211_bitrate_mask *mask; +- u8 num_vht_rates; ++ u8 num_vht_rates, num_he_rates; + u8 link_id = arvif->link_id; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); +@@ -5379,9 +5621,10 @@ static int ath12k_mac_station_assoc(stru + } + + num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask); ++ num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask); + +- /* If single VHT rate is configured (by set_bitrate_mask()), +- * peer_assoc will disable VHT. This is now enabled by a peer specific ++ /* If single VHT/HE rate is configured (by set_bitrate_mask()), ++ * peer_assoc will disable VHT/HE. This is now enabled by a peer specific + * fixed param. + * Note that all other rates and NSS will be disabled for this peer. + */ +@@ -5397,8 +5640,9 @@ static int ath12k_mac_station_assoc(stru + spin_unlock_bh(&ar->data_lock); + + if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) { +- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, +- band); ++ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, band); ++ } else if (link_sta->he_cap.has_he && num_he_rates == 1) { ++ ret = ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band); + if (ret) + return ret; + } +@@ -5462,8 +5706,9 @@ static void ath12k_sta_rc_update_wk(stru + enum nl80211_band band; + const u8 *ht_mcs_mask; + const u16 *vht_mcs_mask; +- u32 changed, bw, nss, smps, bw_prev; +- int err, num_vht_rates; ++ const u16 *he_mcs_mask; ++ u32 changed, bw, nss, mac_nss, smps, bw_prev; ++ int err, num_vht_rates, num_he_rates; + const struct cfg80211_bitrate_mask *mask; + enum wmi_phy_mode peer_phymode; + struct ath12k_link_sta *arsta; +@@ -5483,6 +5728,7 @@ static void ath12k_sta_rc_update_wk(stru + band = def.chan->band; + ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs; + vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs; ++ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; + + spin_lock_bh(&ar->data_lock); + +@@ -5497,8 +5743,10 @@ static void ath12k_sta_rc_update_wk(stru + spin_unlock_bh(&ar->data_lock); + + nss = max_t(u32, 1, nss); +- nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask), +- ath12k_mac_max_vht_nss(vht_mcs_mask))); ++ mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask), ++ ath12k_mac_max_vht_nss(vht_mcs_mask), ++ ath12k_mac_max_he_nss(he_mcs_mask)); ++ nss = min(nss, mac_nss); + + struct ath12k_wmi_peer_assoc_arg *peer_arg __free(kfree) = + kzalloc(sizeof(*peer_arg), GFP_KERNEL); +@@ -5581,6 +5829,8 @@ static void ath12k_sta_rc_update_wk(stru + mask = &arvif->bitrate_mask; + num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, + mask); ++ num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, ++ mask); + + /* Peer_assoc_prepare will reject vht rates in + * bitrate_mask if its not available in range format and +@@ -5603,11 +5853,24 @@ static void ath12k_sta_rc_update_wk(stru + if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) { + ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, + band); ++ } else if (link_sta->he_cap.has_he && num_he_rates == 1) { ++ ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band); + } else { +- /* If the peer is non-VHT or no fixed VHT rate ++ /* If the peer is non-VHT/HE or no fixed VHT/HE rate + * is provided in the new bitrate mask we set the +- * other rates using peer_assoc command. ++ * other rates using peer_assoc command. Also clear ++ * the peer fixed rate settings as it has higher proprity ++ * than peer assoc + */ ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, ++ arvif->vdev_id, ++ WMI_PEER_PARAM_FIXED_RATE, ++ WMI_FIXED_RATE_NONE); ++ if (err) ++ ath12k_warn(ar->ab, ++ "failed to disable peer fixed rate for STA %pM ret %d\n", ++ arsta->addr, err); ++ + ath12k_peer_assoc_prepare(ar, arvif, arsta, + peer_arg, true); + +@@ -11036,19 +11299,40 @@ ath12k_mac_has_single_legacy_rate(struct + if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask)) + return false; + ++ if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask)) ++ return false; ++ + return num_rates == 1; + } + ++static __le16 ++ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap) ++{ ++ if (he_cap->he_cap_elem.phy_cap_info[0] & ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) ++ return he_cap->he_mcs_nss_supp.tx_mcs_80p80; ++ ++ if (he_cap->he_cap_elem.phy_cap_info[0] & ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) ++ return he_cap->he_mcs_nss_supp.tx_mcs_160; ++ ++ return he_cap->he_mcs_nss_supp.tx_mcs_80; ++} ++ + static bool + ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar, ++ struct ieee80211_vif *vif, + enum nl80211_band band, + const struct cfg80211_bitrate_mask *mask, + int *nss) + { + struct ieee80211_supported_band *sband = &ar->mac.sbands[band]; + u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); ++ const struct ieee80211_sta_he_cap *he_cap; ++ u16 he_mcs_map = 0; + u8 ht_nss_mask = 0; + u8 vht_nss_mask = 0; ++ u8 he_nss_mask = 0; + int i; + + /* No need to consider legacy here. Basic rates are always present +@@ -11075,7 +11359,24 @@ ath12k_mac_bitrate_mask_get_single_nss(s + return false; + } + +- if (ht_nss_mask != vht_nss_mask) ++ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif); ++ if (!he_cap) ++ return false; ++ ++ he_mcs_map = le16_to_cpu(ath12k_mac_get_tx_mcs_map(he_cap)); ++ ++ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) { ++ if (mask->control[band].he_mcs[i] == 0) ++ continue; ++ ++ if (mask->control[band].he_mcs[i] == ++ ath12k_mac_get_max_he_mcs_map(he_mcs_map, i)) ++ he_nss_mask |= BIT(i); ++ else ++ return false; ++ } ++ ++ if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask) + return false; + + if (ht_nss_mask == 0) +@@ -11122,54 +11423,182 @@ ath12k_mac_get_single_legacy_rate(struct + return 0; + } + +-static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif, +- u32 rate, u8 nss, u8 sgi, u8 ldpc) ++static int ++ath12k_mac_set_fixed_rate_gi_ltf(struct ath12k_link_vif *arvif, u8 he_gi, u8 he_ltf) + { + struct ath12k *ar = arvif->ar; +- u32 vdev_param; + int ret; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n", +- arvif->vdev_id, rate, nss, sgi); ++ /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */ ++ if (he_gi && he_gi != 0xFF) ++ he_gi += 1; + +- vdev_param = WMI_VDEV_PARAM_FIXED_RATE; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- vdev_param, rate); ++ WMI_VDEV_PARAM_SGI, he_gi); + if (ret) { +- ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n", +- rate, ret); ++ ath12k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n", ++ he_gi, ret); + return ret; + } ++ /* start from 1 */ ++ if (he_ltf != 0xFF) ++ he_ltf += 1; + +- vdev_param = WMI_VDEV_PARAM_NSS; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- vdev_param, nss); ++ WMI_VDEV_PARAM_HE_LTF, he_ltf); + if (ret) { +- ath12k_warn(ar->ab, "failed to set nss param %d: %d\n", +- nss, ret); ++ ath12k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n", ++ he_ltf, ret); + return ret; + } ++ return 0; ++} ++ ++static int ++ath12k_mac_set_auto_rate_gi_ltf(struct ath12k_link_vif *arvif, u16 he_gi, u8 he_ltf) ++{ ++ struct ath12k *ar = arvif->ar; ++ int ret; ++ u32 he_ar_gi_ltf; ++ ++ if (he_gi != 0xFF) { ++ switch (he_gi) { ++ case NL80211_RATE_INFO_HE_GI_0_8: ++ he_gi = WMI_AUTORATE_800NS_GI; ++ break; ++ case NL80211_RATE_INFO_HE_GI_1_6: ++ he_gi = WMI_AUTORATE_1600NS_GI; ++ break; ++ case NL80211_RATE_INFO_HE_GI_3_2: ++ he_gi = WMI_AUTORATE_3200NS_GI; ++ break; ++ default: ++ ath12k_warn(ar->ab, "Invalid GI\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (he_ltf != 0xFF) { ++ switch (he_ltf) { ++ case NL80211_RATE_INFO_HE_1XLTF: ++ he_ltf = WMI_HE_AUTORATE_LTF_1X; ++ break; ++ case NL80211_RATE_INFO_HE_2XLTF: ++ he_ltf = WMI_HE_AUTORATE_LTF_2X; ++ break; ++ case NL80211_RATE_INFO_HE_4XLTF: ++ he_ltf = WMI_HE_AUTORATE_LTF_4X; ++ break; ++ default: ++ ath12k_warn(ar->ab, "Invalid LTF\n"); ++ return -EINVAL; ++ } ++ } ++ ++ he_ar_gi_ltf = he_gi | he_ltf; + +- vdev_param = WMI_VDEV_PARAM_SGI; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- vdev_param, sgi); ++ WMI_VDEV_PARAM_AUTORATE_MISC_CFG, ++ he_ar_gi_ltf); + if (ret) { +- ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n", +- sgi, ret); ++ ath12k_warn(ar->ab, ++ "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n", ++ he_gi, he_ltf, ret); + return ret; + } + +- vdev_param = WMI_VDEV_PARAM_LDPC; ++ return 0; ++} ++ ++static u32 ath12k_mac_nlgi_to_wmigi(enum nl80211_txrate_gi gi) ++{ ++ switch (gi) { ++ case NL80211_TXRATE_DEFAULT_GI: ++ return WMI_GI_400_NS; ++ case NL80211_TXRATE_FORCE_LGI: ++ return WMI_GI_800_NS; ++ default: ++ return WMI_GI_400_NS; ++ } ++} ++ ++static int ath12k_mac_set_rate_params(struct ath12k_link_vif *arvif, ++ u32 rate, u8 nss, u8 sgi, u8 ldpc, ++ u8 he_gi, u8 he_ltf, bool he_fixed_rate) ++{ ++ struct ieee80211_bss_conf *link_conf; ++ struct ath12k *ar = arvif->ar; ++ u32 vdev_param; ++ u32 param_value; ++ int ret; ++ bool he_support; ++ ++ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ++ ++ link_conf = ath12k_mac_get_link_bss_conf(arvif); ++ if (!link_conf) ++ return -EINVAL; ++ ++ he_support = link_conf->he_support; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x\n", ++ arvif->vdev_id, rate, nss, sgi, ldpc); ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", he_gi, ++ he_ltf, he_fixed_rate); ++ ++ if (!he_support) { ++ vdev_param = WMI_VDEV_PARAM_FIXED_RATE; ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ vdev_param, rate); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n", ++ rate, ret); ++ return ret; ++ } ++ } ++ ++ vdev_param = WMI_VDEV_PARAM_NSS; ++ + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- vdev_param, ldpc); ++ vdev_param, nss); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set nss param %d: %d\n", ++ nss, ret); ++ return ret; ++ } ++ ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ WMI_VDEV_PARAM_LDPC, ldpc); + if (ret) { + ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n", + ldpc, ret); + return ret; + } + ++ if (he_support) { ++ if (he_fixed_rate) ++ ret = ath12k_mac_set_fixed_rate_gi_ltf(arvif, he_gi, he_ltf); ++ else ++ ret = ath12k_mac_set_auto_rate_gi_ltf(arvif, he_gi, he_ltf); ++ if (ret) ++ return ret; ++ } else { ++ vdev_param = WMI_VDEV_PARAM_SGI; ++ param_value = ath12k_mac_nlgi_to_wmigi(sgi); ++ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ vdev_param, param_value); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n", ++ sgi, ret); ++ return ret; ++ } ++ } ++ + return 0; + } + +@@ -11198,6 +11627,31 @@ ath12k_mac_vht_mcs_range_present(struct + return true; + } + ++static bool ++ath12k_mac_he_mcs_range_present(struct ath12k *ar, ++ enum nl80211_band band, ++ const struct cfg80211_bitrate_mask *mask) ++{ ++ int i; ++ u16 he_mcs; ++ ++ for (i = 0; i < NL80211_HE_NSS_MAX; i++) { ++ he_mcs = mask->control[band].he_mcs[i]; ++ ++ switch (he_mcs) { ++ case 0: ++ case BIT(8) - 1: ++ case BIT(10) - 1: ++ case BIT(12) - 1: ++ break; ++ default: ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static void ath12k_mac_set_bitrate_mask_iter(void *data, + struct ieee80211_sta *sta) + { +@@ -11206,7 +11660,10 @@ static void ath12k_mac_set_bitrate_mask_ + struct ath12k_link_sta *arsta; + struct ath12k *ar = arvif->ar; + +- arsta = rcu_dereference(ahsta->link[arvif->link_id]); ++ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); ++ ++ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy, ++ ahsta->link[arvif->link_id]); + if (!arsta || arsta->arvif != arvif) + return; + +@@ -11244,6 +11701,61 @@ static void ath12k_mac_disable_peer_fixe + arsta->addr, ret); + } + ++static bool ++ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band band, ++ const struct cfg80211_bitrate_mask *mask, ++ unsigned int link_id) ++{ ++ bool he_fixed_rate = false, vht_fixed_rate = false; ++ const u16 *vht_mcs_mask, *he_mcs_mask; ++ struct ieee80211_link_sta *link_sta; ++ struct ath12k_peer *peer, *tmp; ++ u8 vht_nss, he_nss; ++ int ret = true; ++ ++ vht_mcs_mask = mask->control[band].vht_mcs; ++ he_mcs_mask = mask->control[band].he_mcs; ++ ++ if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1) ++ vht_fixed_rate = true; ++ ++ if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1) ++ he_fixed_rate = true; ++ ++ if (!vht_fixed_rate && !he_fixed_rate) ++ return true; ++ ++ vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask); ++ he_nss = ath12k_mac_max_he_nss(he_mcs_mask); ++ ++ rcu_read_lock(); ++ spin_lock_bh(&ar->ab->base_lock); ++ list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { ++ if (peer->sta) { ++ link_sta = rcu_dereference(peer->sta->link[link_id]); ++ if (!link_sta) { ++ ret = false; ++ goto exit; ++ } ++ ++ if (vht_fixed_rate && (!link_sta->vht_cap.vht_supported || ++ link_sta->rx_nss < vht_nss)) { ++ ret = false; ++ goto exit; ++ } ++ if (he_fixed_rate && (!link_sta->he_cap.has_he || ++ link_sta->rx_nss < he_nss)) { ++ ret = false; ++ goto exit; ++ } ++ } ++ } ++exit: ++ spin_unlock_bh(&ar->ab->base_lock); ++ rcu_read_unlock(); ++ return ret; ++} ++ + static int + ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -11256,13 +11768,17 @@ ath12k_mac_op_set_bitrate_mask(struct ie + enum nl80211_band band; + const u8 *ht_mcs_mask; + const u16 *vht_mcs_mask; ++ const u16 *he_mcs_mask; ++ u8 he_ltf = 0; ++ u8 he_gi = 0; + u32 rate; +- u8 nss; ++ u8 nss, mac_nss; + u8 sgi; + u8 ldpc; + int single_nss; + int ret; + int num_rates; ++ bool he_fixed_rate = false; + + lockdep_assert_wiphy(hw->wiphy); + +@@ -11277,14 +11793,18 @@ ath12k_mac_op_set_bitrate_mask(struct ie + band = def.chan->band; + ht_mcs_mask = mask->control[band].ht_mcs; + vht_mcs_mask = mask->control[band].vht_mcs; ++ he_mcs_mask = mask->control[band].he_mcs; + ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); + + sgi = mask->control[band].gi; +- if (sgi == NL80211_TXRATE_FORCE_LGI) { ++ if (sgi == NL80211_TXRATE_FORCE_SGI) { + ret = -EINVAL; + goto out; + } + ++ he_gi = mask->control[band].he_gi; ++ he_ltf = mask->control[band].he_ltf; ++ + /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it + * requires passing at least one of used basic rates along with them. + * Fixed rate setting across different preambles(legacy, HT, VHT) is +@@ -11301,18 +11821,31 @@ ath12k_mac_op_set_bitrate_mask(struct ie + arvif->vdev_id, ret); + goto out; + } ++ + ieee80211_iterate_stations_mtx(hw, + ath12k_mac_disable_peer_fixed_rate, + arvif); +- } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask, ++ } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, vif, band, mask, + &single_nss)) { + rate = WMI_FIXED_RATE_NONE; + nss = single_nss; ++ arvif->bitrate_mask = *mask; ++ ++ ieee80211_iterate_stations_atomic(hw, ++ ath12k_mac_set_bitrate_mask_iter, ++ arvif); + } else { + rate = WMI_FIXED_RATE_NONE; +- nss = min_t(u32, ar->num_tx_chains, +- max(ath12k_mac_max_ht_nss(ht_mcs_mask), +- ath12k_mac_max_vht_nss(vht_mcs_mask))); ++ ++ if (!ath12k_mac_validate_fixed_rate_settings(ar, band, ++ mask, arvif->link_id)) ++ ath12k_warn(ar->ab, ++ "failed to update fixed rate settings due to mcs/nss incompatibility\n"); ++ ++ mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask), ++ ath12k_mac_max_vht_nss(vht_mcs_mask), ++ ath12k_mac_max_he_nss(he_mcs_mask)); ++ nss = min_t(u32, ar->num_tx_chains, mac_nss); + + /* If multiple rates across different preambles are given + * we can reconfigure this info with all peers using PEER_ASSOC +@@ -11344,9 +11877,21 @@ ath12k_mac_op_set_bitrate_mask(struct ie + */ + ath12k_warn(ar->ab, + "Setting more than one MCS Value in bitrate mask not supported\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto out; + } + ++ num_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask); ++ if (num_rates == 1) ++ he_fixed_rate = true; ++ ++ if (!ath12k_mac_he_mcs_range_present(ar, band, mask) && ++ num_rates > 1) { ++ ath12k_warn(ar->ab, ++ "Setting more than one HE MCS Value in bitrate mask not supported\n"); ++ ret = -EINVAL; ++ goto out; ++ } + ieee80211_iterate_stations_mtx(hw, + ath12k_mac_disable_peer_fixed_rate, + arvif); +@@ -11357,9 +11902,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie + arvif); + } + +- ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc); ++ ret = ath12k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi, ++ he_ltf, he_fixed_rate); + if (ret) { +- ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n", ++ ath12k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n", + arvif->vdev_id, ret); + } + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -222,6 +222,22 @@ enum WMI_HOST_WLAN_BAND { + WMI_HOST_WLAN_2GHZ_5GHZ_CAP = 3, + }; + ++/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command. ++ * Used only for HE auto rate mode. ++ */ ++enum { ++ /* HE LTF related configuration */ ++ WMI_HE_AUTORATE_LTF_1X = BIT(0), ++ WMI_HE_AUTORATE_LTF_2X = BIT(1), ++ WMI_HE_AUTORATE_LTF_4X = BIT(2), ++ ++ /* HE GI related configuration */ ++ WMI_AUTORATE_400NS_GI = BIT(8), ++ WMI_AUTORATE_800NS_GI = BIT(9), ++ WMI_AUTORATE_1600NS_GI = BIT(10), ++ WMI_AUTORATE_3200NS_GI = BIT(11), ++}; ++ + enum wmi_cmd_group { + /* 0 to 2 are reserved */ + WMI_GRP_START = 0x3, +@@ -1169,7 +1185,9 @@ enum wmi_tlv_vdev_param { + WMI_VDEV_PARAM_HE_RANGE_EXT, + WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE, + WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME, ++ WMI_VDEV_PARAM_HE_LTF = 0x74, + WMI_VDEV_PARAM_BA_MODE = 0x7e, ++ WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80, + WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87, + WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99, + WMI_VDEV_PARAM_PROTOTYPE = 0x8000, +@@ -3631,6 +3649,15 @@ struct wmi_force_fw_hang_cmd { + __le32 delay_time_ms; + } __packed; + ++/* Param values to be sent for WMI_VDEV_PARAM_SGI param_id ++ * which are used in 11n, 11ac systems ++ * @WMI_GI_800_NS - Always uses 0.8us (Long GI) ++ * @WMI_GI_400_NS - Firmware switches between 0.4us (Short GI) ++ * and 0.8us (Long GI) based on packet error rate. ++ */ ++#define WMI_GI_800_NS 0 ++#define WMI_GI_400_NS 1 ++ + struct wmi_vdev_set_param_cmd { + __le32 tlv_header; + __le32 vdev_id; diff --git a/patches/ath12k/104-7-wifi-ath12k-clean-up-80P80-support.patch b/patches/ath12k/104-7-wifi-ath12k-clean-up-80P80-support.patch new file mode 100644 index 0000000..55c9aa9 --- /dev/null +++ b/patches/ath12k/104-7-wifi-ath12k-clean-up-80P80-support.patch @@ -0,0 +1,262 @@ +From patchwork Wed May 21 22:45:37 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096121 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED55023958A + for ; Wed, 21 May 2025 22:45:58 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867560; cv=none; + b=R6R1l/0hUMYWkLzVM4w8Z2s3aU01ujlrdBV4IEYLrqQ3CzuP8xd2fnZMcdbVAFvXd/hepJKOZrFod6RG43u2TuGCQ5wM3SKIqyk0c/MlskZk+jnUnvm9WtrezJS82phw1G2mJ8NiYsKzmcJGMQtaYfl3jWA4o+BGMGyOg0Keb/M= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867560; c=relaxed/simple; + bh=HUqzq2V1sSbcLZxqxveNb5xXvMg5sfyIhSzn4mKsdms=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=G9poRT2jwhhAC0htiaG4SIE8b1DuTf63uDCDCGj5WoQ4B/v/NWtaqtzBWJF4c7UuQBso4JO4X9auJyfxJ4SxUBrULdlJq7mvAs7nxFOPEBDBltLKWCZznLwuuuo690MjvUQ5mfKt/Oy+uREyur4vXsQtfSBZc0DSZUlC5R+Z2Mc= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=cu63IdMd; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="cu63IdMd" +Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LJgw7Z025025; + Wed, 21 May 2025 22:45:56 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + 90lF32RvbNU2yyxl2mGBEewKfDvRJ7MRRLe6DgCwXFs=; b=cu63IdMdS+nJIsqy + ktY/ZQ/qTTWf2MpubSMC9UftiwnI9Xj6K8LFE0q+NvCN2EgZKzf+OzyW9wbbRepN + Q3ZYBAR3lFyw40J6AZgpAuPiq7Y+eqt7l8jc+/2bb2+imOzvWHwFkXSvc8nijnHX + ZLEU29M0xloyHeJ7xLbumzRdfcCJ6357/HKp9U3mLvEfpLY97t5/H3yEJWHQmnvE + aHkFaLM6Ru2R2+nzPDylKcY+TZsqv306oEqydWI33ANyvfDkWJqbQjtQ+geTkJxC + syi9ZifD5zPdOjb9YWNn0V8mWUBRx6hW8ZKU/L3gWGXjkvyRHneZ4AOz83Tp9Ym4 + L34jSQ== +Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf6vbsf-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:55 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjsWN022226 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:54 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:54 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Jeff Johnson +Subject: [PATCH ath-next V14 7/9] wifi: ath12k: clean up 80P80 support +Date: Wed, 21 May 2025 15:45:37 -0700 +Message-ID: <20250521224539.355985-8-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-GUID: xDBdjIlSrmWJZkBfMwcImhxnyTIR4551 +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX75XKL//oF16a + YMA/60ZSduIYMzTQ+PpEhRfS8BSEJ3JAYNLLDjp3b1hmrHJmdqMnxgbya6RQ+qeAISgkr8ZWIMx + fGx/btrlFP2SbXd0JWwSMOApD3LJewBu/ZeBWBDEWbbO00LOGnR0aFqmCeym6YSeYyakVcNd8nQ + 0JnPxxBLeXeYPpIZTFMD6TpVFyfvtCG9jpMOI27FLBdHLednVW2yrOx5b62xwy181re5iN4XOki + 1M/HJRMACpfQJImHpO9X3rRh2j79oKIKVwa3UjV8A7vD3noV/pV0SOTZP0awMYQH/Pn91nji685 + auXzHG2pai3Byw89+jYZIG2xfiqBcBwIEARvw52XSv3glk0tSvLDxNo8nyFNPsZ63g70USl1IlC + AKhW+QOw9/zkn3oCB+3fZZ/y+F4vlu4OzN4gETU+6p3798YiFGWMvocQnI/Ig7Unex9rmOP5 +X-Authority-Analysis: v=2.4 cv=fZOty1QF c=1 sm=1 tr=0 ts=682e57a3 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=QHHbJxpVzSBZVvfXPLwA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-ORIG-GUID: xDBdjIlSrmWJZkBfMwcImhxnyTIR4551 +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + clxscore=1015 mlxscore=0 adultscore=0 spamscore=0 bulkscore=0 suspectscore=0 + malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999 + lowpriorityscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a + authcc= route=outbound adjust=0 reason=mlx scancount=1 + engine=8.19.0-2505160000 definitions=main-2505210226 + +Clean up unused 80P80 references as hardware does not support +it. This is applicable to both QCN9274 and WCN7850. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/mac.c | 48 ++++++--------------------- + drivers/net/wireless/ath/ath12k/wmi.c | 2 -- + drivers/net/wireless/ath/ath12k/wmi.h | 1 - + 3 files changed, 10 insertions(+), 41 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -209,7 +209,7 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12 + [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40, + [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80, + [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160, +- [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80, ++ [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN, + [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320, + }, + [NL80211_BAND_6GHZ] = { +@@ -220,7 +220,7 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12 + [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40, + [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80, + [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160, +- [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80, ++ [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN, + [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320, + }, + +@@ -2556,17 +2556,6 @@ static void ath12k_peer_assoc_h_he(struc + + switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_160: +- if (he_cap->he_cap_elem.phy_cap_info[0] & +- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) { +- v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask); +- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v; +- +- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80); +- arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v; +- +- arg->peer_he_mcs_count++; +- he_tx_mcs = v; +- } + v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); + arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v; + +@@ -2853,16 +2842,11 @@ static enum wmi_phy_mode ath12k_mac_get_ + struct ieee80211_link_sta *link_sta) + { + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { +- switch (link_sta->vht_cap.cap & +- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { +- case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: ++ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) + return MODE_11AC_VHT160; +- case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: +- return MODE_11AC_VHT80_80; +- default: +- /* not sure if this is a valid case? */ +- return MODE_11AC_VHT160; +- } ++ ++ /* not sure if this is a valid case? */ ++ return MODE_11AC_VHT160; + } + + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) +@@ -2884,11 +2868,8 @@ static enum wmi_phy_mode ath12k_mac_get_ + if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11AX_HE160; +- else if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] & +- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) +- return MODE_11AX_HE80_80; +- /* not sure if this is a valid case? */ +- return MODE_11AX_HE160; ++ ++ return MODE_UNKNOWN; + } + + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) +@@ -2916,14 +2897,10 @@ static enum wmi_phy_mode ath12k_mac_get_ + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11BE_EHT160; + +- if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] & +- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) +- return MODE_11BE_EHT80_80; +- + ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n", + link_sta->he_cap.he_cap_elem.phy_cap_info[0]); + +- return MODE_11BE_EHT160; ++ return MODE_UNKNOWN; + } + + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) +@@ -7630,8 +7607,6 @@ static void ath12k_mac_set_hemcsmap(stru + mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff); + mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff); + mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff); +- mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff); +- mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff); + } + + static void ath12k_mac_copy_he_cap(struct ath12k *ar, +@@ -7653,6 +7628,7 @@ static void ath12k_mac_copy_he_cap(struc + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; ++ /* 80PLUS80 is not supported */ + he_cap_elem->phy_cap_info[0] &= + ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; + he_cap_elem->phy_cap_info[5] &= +@@ -11309,10 +11285,6 @@ static __le16 + ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap) + { + if (he_cap->he_cap_elem.phy_cap_info[0] & +- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) +- return he_cap->he_mcs_nss_supp.tx_mcs_80p80; +- +- if (he_cap->he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return he_cap->he_mcs_nss_supp.tx_mcs_160; + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1066,8 +1066,6 @@ static void ath12k_wmi_put_wmi_channel(s + chan->band_center_freq1 = cpu_to_le32(center_freq1 - 40); + + chan->band_center_freq2 = cpu_to_le32(center_freq1); +- } else if (arg->mode == MODE_11BE_EHT80_80) { +- chan->band_center_freq2 = cpu_to_le32(arg->band_center_freq2); + } else { + chan->band_center_freq2 = 0; + } +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3798,7 +3798,6 @@ struct wmi_vdev_install_key_arg { + #define WMI_HOST_MAX_HE_RATE_SET 3 + #define WMI_HECAP_TXRX_MCS_NSS_IDX_80 0 + #define WMI_HECAP_TXRX_MCS_NSS_IDX_160 1 +-#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80 2 + + #define ATH12K_WMI_MLO_MAX_PARTNER_LINKS \ + (ATH12K_WMI_MLO_MAX_LINKS + ATH12K_MAX_NUM_BRIDGE_LINKS - 1) diff --git a/patches/ath12k/104-8-wifi-ath12k-add-support-for-160-MHz-bandwidth.patch b/patches/ath12k/104-8-wifi-ath12k-add-support-for-160-MHz-bandwidth.patch new file mode 100644 index 0000000..aeaeefe --- /dev/null +++ b/patches/ath12k/104-8-wifi-ath12k-add-support-for-160-MHz-bandwidth.patch @@ -0,0 +1,379 @@ +From patchwork Wed May 21 22:45:38 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096124 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id DEE9223A9AA + for ; Wed, 21 May 2025 22:45:59 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867561; cv=none; + b=qWgm5H8L0Zhrc5crkCw7SBoGEQ8yf+aC0TSWOzfiTwcAddeStpjorEa3XaBl0GOhHPRaECOhMSNqu88tQ5CzCGmumBQ3QLC6mod6Tb0Y0PdeUJm3YoGKcI+F0oE3g5kCHaU9LRKKnmMZQS72kE7dO+lEBfwMIuCX/VwV066B1p8= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867561; c=relaxed/simple; + bh=61S52HJJJauXcXkg3NpFqkwtGSPNO+bmTpNYu1v9AKM=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=gi5WIxM8SYlljyfdAVTdIK6JQ5jJHPGGfdxPkwbtEaPElRA55vurxkaaJ0RktTtDYYJEn7KLZFieBHAv5/nEcrDjL4NGvgT3wiAoGcbsd+TIF6w5J2RSmAwhAP008N5swveLHDzJ0M9TrtQj2HHndc8JPD4oGWbcEqKQqHSq8ck= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=lMYw009C; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="lMYw009C" +Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LJgEPE029249; + Wed, 21 May 2025 22:45:56 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + ph+yJaIkwYsZzzEsymzTjupgmHjdwFMJhbEzuPrYvfY=; b=lMYw009CSvZqDxkz + +HCEzcZhy6QO8G2ut93TJxHdCbVLlRaMNReXGlGqx2KRNracyLRkAQsC16i+QcpJ + aHBvIE2c0/TEtBiyv3HzBf3/89R0POT080sz81P6go3m8w9bcIE+Q2DqjdhVNqu3 + AlV8qb6pj/QUVvDbJQxO1M9eCXSO6g2BBDjgRCktOu+x2TlxhdBZ/tJP+h0AUk+j + YsH1LhcLOZYCFTJyB6IFmHWvtGk5Ef6i6D/tXyCL7nQiDP/R1v2PcdlLlI5e5/PO + FhKB2+RCmSyJUtyaAHHi/mVen5yqFX2K3/vL3BtprRAJINhFxQrLs6xLIQabELzj + KCstuQ== +Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwfb4b3x-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:55 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjtX2022238 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:55 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:54 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + P Praneesh , + "Jeff + Johnson" +Subject: [PATCH ath-next V14 8/9] wifi: ath12k: add support for 160 MHz + bandwidth +Date: Wed, 21 May 2025 15:45:38 -0700 +Message-ID: <20250521224539.355985-9-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-ORIG-GUID: T9MbsOp4F8M93FD6ZEyfm1BTh5tEiCIl +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX0EeEFBAyVxZV + WX6jh2dkCn4P+eViI8Gvz/6S+yZ+Avx9/8To2mbulh5j1kDm92bEDu7iQtI17ILPnOgbUXWAjjt + Z2LvemtbMzJe0lY0EjJNWWunihdlsXPAdOnZFjV0rOtakq8Xx4y8K45/1cGY9dQOApxDFC9HiLZ + +FK9apopZ2DyP6haLf5HQI+6DC3wwgbEQlE+89g69hXEM8UePlFlsf0fpfIVgiWG73gfzHkrRPM + 8ByVGmKpFSXIBmvY+EZZOPuPsQHt/91pIisXw5Joxdbl6Qf2anjuC0X4LPrTgTxgXWhljS4JdXo + djhNt09IBnNuagxN9aMx/frUhqQPNL54kp/cXbpgcLQX0XQg8SOvwyxJs+CALQUyymluDLHyH9w + UQUznCXFrps86AX/Fpnhrl9hqR5NO0/6oR340zsS7mvryRucOqzT7vc3WPMJEhW68VMCAl5Z +X-Proofpoint-GUID: T9MbsOp4F8M93FD6ZEyfm1BTh5tEiCIl +X-Authority-Analysis: v=2.4 cv=dLCmmPZb c=1 sm=1 tr=0 ts=682e57a4 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=dOJm2eNAaUnF9U8lSB4A:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + mlxscore=0 clxscore=1015 adultscore=0 bulkscore=0 phishscore=0 suspectscore=0 + impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0 + priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc= + route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 + definitions=main-2505210226 + +Add support to configure maximum NSS in 160 MHz bandwidth. +Firmware advertises support for handling NSS ratio information +as a part of service ready ext event using nss_ratio_enabled +flag. Save this information in ath12k_pdev_cap to calculate +NSS ratio. + +Additionally, reorder the code by moving +ath12k_peer_assoc_h_phymode() before ath12k_peer_assoc_h_vht() +to ensure that arg->peer_phymode correctly reflects the bandwidth +in the max NSS calculation. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: P Praneesh +Signed-off-by: P Praneesh +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/mac.c | 89 ++++++++++++++++++++++---- + drivers/net/wireless/ath/ath12k/mac.h | 2 + + drivers/net/wireless/ath/ath12k/wmi.c | 7 +- + drivers/net/wireless/ath/ath12k/wmi.h | 28 ++++++++ + 5 files changed, 115 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -879,6 +879,8 @@ struct ath12k_pdev_cap { + struct ath12k_band_cap band[NUM_NL80211_BANDS]; + u32 eml_cap; + u32 mld_cap; ++ bool nss_ratio_enabled; ++ u8 nss_ratio_info; + }; + + struct mlo_timestamp { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -2185,6 +2185,34 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs + return tx_mcs_set; + } + ++static u8 ath12k_get_nss_160mhz(struct ath12k *ar, ++ u8 max_nss) ++{ ++ u8 nss_ratio_info = ar->pdev->cap.nss_ratio_info; ++ u8 max_sup_nss = 0; ++ ++ switch (nss_ratio_info) { ++ case WMI_NSS_RATIO_1BY2_NSS: ++ max_sup_nss = max_nss >> 1; ++ break; ++ case WMI_NSS_RATIO_3BY4_NSS: ++ ath12k_warn(ar->ab, "WMI_NSS_RATIO_3BY4_NSS not supported\n"); ++ break; ++ case WMI_NSS_RATIO_1_NSS: ++ max_sup_nss = max_nss; ++ break; ++ case WMI_NSS_RATIO_2_NSS: ++ ath12k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n"); ++ break; ++ default: ++ ath12k_warn(ar->ab, "invalid nss ratio received from fw: %d\n", ++ nss_ratio_info); ++ break; ++ } ++ ++ return max_sup_nss; ++} ++ + static void ath12k_peer_assoc_h_vht(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, +@@ -2202,6 +2230,7 @@ static void ath12k_peer_assoc_h_vht(stru + u8 max_nss, vht_mcs; + int i, vht_nss, nss_idx; + bool user_rate_valid = true; ++ u32 rx_nss, tx_nss, nss_160; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + +@@ -2306,10 +2335,24 @@ static void ath12k_peer_assoc_h_vht(stru + /* TODO: Check */ + arg->tx_max_mcs_nss = 0xFF; + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n", +- arsta->addr, arg->peer_max_mpdu, arg->peer_flags); ++ if (arg->peer_phymode == MODE_11AC_VHT160) { ++ tx_nss = ath12k_get_nss_160mhz(ar, max_nss); ++ rx_nss = min(arg->peer_nss, tx_nss); ++ arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE; ++ ++ if (!rx_nss) { ++ ath12k_warn(ar->ab, "invalid max_nss\n"); ++ return; ++ } ++ ++ nss_160 = u32_encode_bits(rx_nss - 1, ATH12K_PEER_RX_NSS_160MHZ); ++ arg->peer_bw_rxnss_override |= nss_160; ++ } + +- /* TODO: rxnss_override */ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n", ++ arsta->addr, arg->peer_max_mpdu, arg->peer_flags, ++ arg->peer_bw_rxnss_override); + } + + static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss) +@@ -2402,6 +2445,7 @@ static void ath12k_peer_assoc_h_he(struc + u16 he_tx_mcs = 0, v = 0; + int he_nss, nss_idx; + bool user_rate_valid = true; ++ u32 rx_nss, tx_nss, nss_160; + + if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def))) + return; +@@ -2599,9 +2643,25 @@ static void ath12k_peer_assoc_h_he(struc + max_nss = min(max_nss, ar->num_tx_chains); + arg->peer_nss = min(link_sta->rx_nss, max_nss); + ++ if (arg->peer_phymode == MODE_11AX_HE160) { ++ tx_nss = ath12k_get_nss_160mhz(ar, max_nss); ++ rx_nss = min(arg->peer_nss, tx_nss); ++ arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE; ++ ++ if (!rx_nss) { ++ ath12k_warn(ar->ab, "invalid max_nss\n"); ++ return; ++ } ++ ++ nss_160 = u32_encode_bits(rx_nss - 1, ATH12K_PEER_RX_NSS_160MHZ); ++ arg->peer_bw_rxnss_override |= nss_160; ++ } ++ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +- "mac he peer %pM nss %d mcs cnt %d\n", +- arsta->addr, arg->peer_nss, arg->peer_he_mcs_count); ++ "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n", ++ arsta->addr, arg->peer_nss, ++ arg->peer_he_mcs_count, ++ arg->peer_bw_rxnss_override); + } + + static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar, +@@ -2842,10 +2902,13 @@ static enum wmi_phy_mode ath12k_mac_get_ + struct ieee80211_link_sta *link_sta) + { + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { +- if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) ++ if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | ++ IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)) + return MODE_11AC_VHT160; + +- /* not sure if this is a valid case? */ ++ /* Allow STA to connect even if it does not explicitly advertise 160 MHz ++ * support ++ */ + return MODE_11AC_VHT160; + } + +@@ -7379,10 +7442,8 @@ ath12k_create_vht_cap(struct ath12k *ar, + + ath12k_set_vht_txbf_cap(ar, &vht_cap.cap); + +- /* TODO: Enable back VHT160 mode once association issues are fixed */ +- /* Disabling VHT160 and VHT80+80 modes */ +- vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; +- vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160; ++ /* 80P80 is not supported */ ++ vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + + rxmcs_map = 0; + txmcs_map = 0; +@@ -12654,7 +12715,8 @@ ath12k_mac_setup_radio_iface_comb(struct + comb[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | +- BIT(NL80211_CHAN_WIDTH_80); ++ BIT(NL80211_CHAN_WIDTH_80) | ++ BIT(NL80211_CHAN_WIDTH_160); + } + + return 0; +@@ -13031,6 +13093,9 @@ static int ath12k_mac_hw_register(struct + ieee80211_hw_set(hw, REPORTS_LOW_ACK); + ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR); + ++ if (cap->nss_ratio_enabled) ++ ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); ++ + if ((ht_cap & WMI_HT_CAP_ENABLED) || is_6ghz) { + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -41,6 +41,8 @@ struct ath12k_generic_iter { + #define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24) + + #define ATH12K_CHAN_WIDTH_NUM 14 ++#define ATH12K_BW_NSS_MAP_ENABLE BIT(31) ++#define ATH12K_PEER_RX_NSS_160MHZ GENMASK(2, 0) + + #define ATH12K_TX_POWER_MAX_VAL 70 + #define ATH12K_TX_POWER_MIN_VAL 0 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -537,6 +537,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(st + pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g); + pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_5g); + pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_5g); ++ pdev_cap->nss_ratio_enabled = ++ WMI_NSS_RATIO_EN_DIS_GET(mac_caps->nss_ratio); ++ pdev_cap->nss_ratio_info = ++ WMI_NSS_RATIO_INFO_GET(mac_caps->nss_ratio); + } else { + return -EINVAL; + } +@@ -1059,7 +1063,8 @@ static void ath12k_wmi_put_wmi_channel(s + + chan->band_center_freq2 = cpu_to_le32(center_freq1); + +- } else if (arg->mode == MODE_11BE_EHT160) { ++ } else if (arg->mode == MODE_11BE_EHT160 || ++ arg->mode == MODE_11AX_HE160) { + if (arg->freq > center_freq1) + chan->band_center_freq1 = cpu_to_le32(center_freq1 + 40); + else +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2328,6 +2328,21 @@ enum wmi_direct_buffer_module { + WMI_DIRECT_BUF_MAX + }; + ++/** ++ * enum wmi_nss_ratio - NSS ratio received from FW during service ready ext event ++ * @WMI_NSS_RATIO_1BY2_NSS: Max nss of 160MHz is equals to half of the max nss of 80MHz ++ * @WMI_NSS_RATIO_3BY4_NSS: Max nss of 160MHz is equals to 3/4 of the max nss of 80MHz ++ * @WMI_NSS_RATIO_1_NSS: Max nss of 160MHz is equals to the max nss of 80MHz ++ * @WMI_NSS_RATIO_2_NSS: Max nss of 160MHz is equals to two times the max nss of 80MHz ++ */ ++ ++enum wmi_nss_ratio { ++ WMI_NSS_RATIO_1BY2_NSS, ++ WMI_NSS_RATIO_3BY4_NSS, ++ WMI_NSS_RATIO_1_NSS, ++ WMI_NSS_RATIO_2_NSS ++}; ++ + struct ath12k_wmi_pdev_band_arg { + u32 pdev_id; + u32 start_freq; +@@ -2647,6 +2662,12 @@ struct ath12k_wmi_hw_mode_cap_params { + } __packed; + + #define WMI_MAX_HECAP_PHY_SIZE (3) ++#define WMI_NSS_RATIO_EN_DIS_BITPOS BIT(0) ++#define WMI_NSS_RATIO_EN_DIS_GET(_val) \ ++ le32_get_bits(_val, WMI_NSS_RATIO_EN_DIS_BITPOS) ++#define WMI_NSS_RATIO_INFO_BITPOS GENMASK(4, 1) ++#define WMI_NSS_RATIO_INFO_GET(_val) \ ++ le32_get_bits(_val, WMI_NSS_RATIO_INFO_BITPOS) + + /* pdev_id is present in lower 16 bits of pdev_and_hw_link_ids in + * ath12k_wmi_mac_phy_caps_params & ath12k_wmi_caps_ext_params. diff --git a/patches/ath12k/104-9-wifi-ath12k-add-extended-NSS-bandwidth-support-for-160-MHz.patch b/patches/ath12k/104-9-wifi-ath12k-add-extended-NSS-bandwidth-support-for-160-MHz.patch new file mode 100644 index 0000000..fd618f7 --- /dev/null +++ b/patches/ath12k/104-9-wifi-ath12k-add-extended-NSS-bandwidth-support-for-160-MHz.patch @@ -0,0 +1,202 @@ +From patchwork Wed May 21 22:45:39 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Pradeep Kumar Chitrapu +X-Patchwork-Id: 14096122 +X-Patchwork-Delegate: quic_jjohnson@quicinc.com +Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com + [205.220.180.131]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A1E9239E85 + for ; Wed, 21 May 2025 22:45:59 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=205.220.180.131 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1747867561; cv=none; + b=YNQGoLeTsEUX0an1dYT8uFrTBxczoxLPoB0nXP+MEP3YMcemaxVf4zoi5GMSuKPLe4yeLz/R7AB090SrXrBTbY6MmwXLrUJGFBQUGwr05KQ5BnedSLyVE+PtNo01ZVjrjprsc5LC4z0vYHmQdBsqIfqP+bb+ATVkdkkKWV4Kg3A= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1747867561; c=relaxed/simple; + bh=WkoD1wqfpiPds2ZNAwn7TY38LnC6cJOAuobqk3tWbSk=; + h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: + MIME-Version:Content-Type; + b=aAO1mDb/PrwqKRHoeS0PAxgJAvDLPWPPBkzRX0hwJbFzcXtKdtWHDE83rjGbjR1bnM7lhkAU4SwoT87sOuciveNqdywUe6+9XTB2oWM/j0Tza/ZRKKRZFeByh7ib8Aibzc4y0ACg7Oaz/QhmWmPObPjc4oKuVzaH/P8Tub0rBcI= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com; + spf=pass smtp.mailfrom=quicinc.com; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b=o3M+Sjyr; arc=none smtp.client-ip=205.220.180.131 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=quicinc.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com + header.b="o3M+Sjyr" +Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) + by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id + 54LJHZNq001758; + Wed, 21 May 2025 22:45:56 GMT +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= + cc:content-transfer-encoding:content-type:date:from:in-reply-to + :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= + wh8AVrVaz3Wne8xUCnRodQGPYbrNE8Rm9/NepU3KoQA=; b=o3M+SjyriKBrU+dH + +Uwb/f5RzskxDlOAgOvwNH7O5p766ueJYE/nAazyAuVI1fbDT1gkgvOM4VOLQAPP + zg9tDUD5Mz80GzBzSnheYbeedz7RgpaN14Qr6Gz/+1yrP4wWTh2quGduIAXBFDZR + QpWsQh2DxVOvXqoLRm64iurJNhvpq+YIAwpAxEA9Fp46SrXsFefc82nza6qgdk5P + pUjalFWnwLLxaSHJj2EoJhFDAf99q9N5KNKW/UCNY8A2CwQXqL9KmggTLRK1OC+S + ueHigeV9ydoGGD1W6zmEdydGv5JSaQRhjAxtJokUtrlUwn8mbpJyokm+Ie4GZV5v + tie1qQ== +Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com + [129.46.96.20]) + by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf6vbsg-1 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:56 +0000 (GMT) +Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com + [10.47.209.196]) + by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id + 54LMjtcB022245 + (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); + Wed, 21 May 2025 22:45:55 GMT +Received: from ath12k-linux2.qualcomm.com (10.80.80.8) by + nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server + (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id + 15.2.1544.9; Wed, 21 May 2025 15:45:54 -0700 +From: Pradeep Kumar Chitrapu +To: +CC: , + Pradeep Kumar Chitrapu + , + Jeff Johnson +Subject: [PATCH ath-next V14 9/9] wifi: ath12k: add extended NSS bandwidth + support for 160 MHz +Date: Wed, 21 May 2025 15:45:39 -0700 +Message-ID: <20250521224539.355985-10-quic_pradeepc@quicinc.com> +X-Mailer: git-send-email 2.43.0 +In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +References: <20250521224539.355985-1-quic_pradeepc@quicinc.com> +Precedence: bulk +X-Mailing-List: linux-wireless@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To + nalasex01a.na.qualcomm.com (10.47.209.196) +X-QCInternal: smtphost +X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 + signatures=585085 +X-Proofpoint-GUID: 3XlPaBNySyE2wx5TC6p1DVWVXzadsV9U +X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX4g8vKznbpwuH + ZKoHe/eZESaXJ/nU0MF27s2mZH9kbhxkG1nYDBAxgIAR6HSB4Ir8V8BP9wvETNPaaV4xpgjbT6m + sDGIplm3HpwbpmQYiBtQIsOrs/s1B2t7uVdhqW02FHlFu/UIBLwZc7J8sLJcsYdxHYcx7MQ3nEe + tDoPrPTEwHw7n1CnzcfVsEUAuxuJ5iFaxBATgZF+LuAhijNvhyaoEWRUO2KUcBJaFHq/QbCYfpY + JBXWUNl+mlZxfQe4pogCpRmvEOONRvpKgZLFdEAxf2Fx0Z7OhaIV84gi99TYTjfe1aihjorJ/cp + cv78Jzcd3Pe3GwTFD0ZOqI30oSiaUyJS3E9XIjfDGLAVMK6FeM+KOYgnqo95ImgBH8HRshrA4LJ + qTKv2kKP1y4zPtpf7lmI2mcl7emiLGQx+t0d7Z8upCbYseoNAGHUkFJ45HF940Za9ZkEYTRq +X-Authority-Analysis: v=2.4 cv=fZOty1QF c=1 sm=1 tr=0 ts=682e57a4 cx=c_pps + a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 + a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=Opr4SxZhII4Vei-TI5AA:9 + a=TjNXssC_j7lpFel5tvFf:22 +X-Proofpoint-ORIG-GUID: 3XlPaBNySyE2wx5TC6p1DVWVXzadsV9U +X-Proofpoint-Virus-Version: vendor=baseguard + engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 + definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01 +X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 + clxscore=1015 mlxscore=0 adultscore=0 spamscore=0 bulkscore=0 suspectscore=0 + malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999 + lowpriorityscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a + authcc= route=outbound adjust=0 reason=mlx scancount=1 + engine=8.19.0-2505160000 definitions=main-2505210226 + +Currently rx and tx MCS map for 160 MHz under HE capabilities +are not updating properly, when 160 MHz is configured with NSS +lesser than max NSS support. Fix this by utilizing +nss_ratio_enabled and nss_ratio_info fields sent by firmware +in service ready event. + +However, if firmware advertises EXT NSS BW support in VHT caps +as 1(1x2) and when nss_ratio_info indicates 1:1, reset the EXT +NSS BW Support in VHT caps to 0 which indicates 1x1. This is +to avoid incorrectly choosing 1:2 NSS ratio when using the +default VHT caps advertised by firmware. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Pradeep Kumar Chitrapu +Acked-by: Jeff Johnson +--- + drivers/net/wireless/ath/ath12k/mac.c | 33 ++++++++++++++++++++++----- + 1 file changed, 27 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -2644,8 +2644,10 @@ static void ath12k_peer_assoc_h_he(struc + arg->peer_nss = min(link_sta->rx_nss, max_nss); + + if (arg->peer_phymode == MODE_11AX_HE160) { +- tx_nss = ath12k_get_nss_160mhz(ar, max_nss); ++ tx_nss = ath12k_get_nss_160mhz(ar, ar->num_tx_chains); + rx_nss = min(arg->peer_nss, tx_nss); ++ ++ arg->peer_nss = min(link_sta->rx_nss, ar->num_rx_chains); + arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE; + + if (!rx_nss) { +@@ -7465,6 +7467,12 @@ ath12k_create_vht_cap(struct ath12k *ar, + vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map); + vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map); + ++ /* Check if the HW supports 1:1 NSS ratio and reset ++ * EXT NSS BW Support field to 0 to indicate 1:1 ratio ++ */ ++ if (ar->pdev->cap.nss_ratio_info == WMI_NSS_RATIO_1_NSS) ++ vht_cap.cap &= ~IEEE80211_VHT_CAP_EXT_NSS_BW_MASK; ++ + return vht_cap; + } + +@@ -7645,11 +7653,12 @@ static void ath12k_mac_set_hemcsmap(stru + struct ieee80211_sta_he_cap *he_cap) + { + struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp; +- u16 txmcs_map, rxmcs_map; ++ u8 maxtxnss_160 = ath12k_get_nss_160mhz(ar, ar->num_tx_chains); ++ u8 maxrxnss_160 = ath12k_get_nss_160mhz(ar, ar->num_rx_chains); ++ u16 txmcs_map_160 = 0, rxmcs_map_160 = 0; ++ u16 txmcs_map = 0, rxmcs_map = 0; + u32 i; + +- rxmcs_map = 0; +- txmcs_map = 0; + for (i = 0; i < 8; i++) { + if (i < ar->num_tx_chains && + (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) +@@ -7662,12 +7671,24 @@ static void ath12k_mac_set_hemcsmap(stru + rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); + else + rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ ++ if (i < maxtxnss_160 && ++ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ txmcs_map_160 |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ txmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ ++ if (i < maxrxnss_160 && ++ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ rxmcs_map_160 |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ rxmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); + } + + mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff); + mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff); +- mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff); +- mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff); ++ mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map_160 & 0xffff); ++ mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map_160 & 0xffff); + } + + static void ath12k_mac_copy_he_cap(struct ath12k *ar, diff --git a/patches/ath12k/200-Revert-wifi-ath12k-convert-tasklet-to-BH-workqueue-f.patch b/patches/ath12k/200-Revert-wifi-ath12k-convert-tasklet-to-BH-workqueue-f.patch new file mode 100644 index 0000000..9f435f9 --- /dev/null +++ b/patches/ath12k/200-Revert-wifi-ath12k-convert-tasklet-to-BH-workqueue-f.patch @@ -0,0 +1,82 @@ +From cd911185014f773f0e227cabfb760b30968c3bca Mon Sep 17 00:00:00 2001 +From: Mantas Pucka +Date: Tue, 27 May 2025 14:13:27 +0300 +Subject: [PATCH] Revert "wifi: ath12k: convert tasklet to BH workqueue for CE + interrupts" + +This reverts commit cdad737160571a98cc4933a62c9f2728e965ab27. +--- + drivers/net/wireless/ath/ath12k/ce.h | 2 +- + drivers/net/wireless/ath/ath12k/pci.c | 14 +++++++------- + 2 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/ce.h ++++ b/drivers/net/wireless/ath/ath12k/ce.h +@@ -159,7 +159,7 @@ struct ath12k_ce_pipe { + void (*send_cb)(struct ath12k_ce_pipe *pipe); + void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb); + +- struct work_struct intr_wq; ++ struct tasklet_struct intr_tq; + struct ath12k_ce_ring *src_ring; + struct ath12k_ce_ring *dest_ring; + struct ath12k_ce_ring *status_ring; +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -430,9 +430,9 @@ static void ath12k_pci_sync_ce_irqs(stru + } + } + +-static void ath12k_pci_ce_workqueue(struct work_struct *work) ++static void ath12k_pci_ce_tasklet(struct tasklet_struct *t) + { +- struct ath12k_ce_pipe *ce_pipe = from_work(ce_pipe, work, intr_wq); ++ struct ath12k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); + int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; + + ath12k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); +@@ -454,7 +454,7 @@ static irqreturn_t ath12k_pci_ce_interru + + disable_irq_nosync(ab->irq_num[irq_idx]); + +- queue_work(system_bh_wq, &ce_pipe->intr_wq); ++ tasklet_schedule(&ce_pipe->intr_tq); + + return IRQ_HANDLED; + } +@@ -684,7 +684,7 @@ static int ath12k_pci_config_irq(struct + + irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + i; + +- INIT_WORK(&ce_pipe->intr_wq, ath12k_pci_ce_workqueue); ++ tasklet_setup(&ce_pipe->intr_tq, ath12k_pci_ce_tasklet); + + ret = request_irq(irq, ath12k_pci_ce_interrupt_handler, + ab_pci->irq_flags, irq_name[irq_idx], +@@ -967,7 +967,7 @@ static void ath12k_pci_aspm_restore(stru + PCI_EXP_LNKCTL_ASPMC); + } + +-static void ath12k_pci_cancel_workqueue(struct ath12k_base *ab) ++static void ath12k_pci_kill_tasklets(struct ath12k_base *ab) + { + int i; + +@@ -977,7 +977,7 @@ static void ath12k_pci_cancel_workqueue( + if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) + continue; + +- cancel_work_sync(&ce_pipe->intr_wq); ++ tasklet_kill(&ce_pipe->intr_tq); + } + } + +@@ -985,7 +985,7 @@ static void ath12k_pci_ce_irq_disable_sy + { + ath12k_pci_ce_irqs_disable(ab); + ath12k_pci_sync_ce_irqs(ab); +- ath12k_pci_cancel_workqueue(ab); ++ ath12k_pci_kill_tasklets(ab); + } + + int ath12k_pci_map_service_to_pipe(struct ath12k_base *ab, u16 service_id, diff --git a/patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch new file mode 100644 index 0000000..4fc97df --- /dev/null +++ b/patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch @@ -0,0 +1,38 @@ +--- a/drivers/net/wireless/ath/ath5k/initvals.c ++++ b/drivers/net/wireless/ath/ath5k/initvals.c +@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini + { AR5K_IMR, 0 }, + { AR5K_IER, AR5K_IER_DISABLE }, + { AR5K_BSR, 0, AR5K_INI_READ }, ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + { AR5K_TXCFG, AR5K_DMASIZE_128B }, + { AR5K_RXCFG, AR5K_DMASIZE_128B }, ++#else ++ /* WAR for AR71xx PCI bug */ ++ { AR5K_TXCFG, AR5K_DMASIZE_128B }, ++ { AR5K_RXCFG, AR5K_DMASIZE_4B }, ++#endif + { AR5K_CFG, AR5K_INIT_CFG }, + { AR5K_TOPS, 8 }, + { AR5K_RXNOFRM, 8 }, +--- a/drivers/net/wireless/ath/ath5k/dma.c ++++ b/drivers/net/wireless/ath/ath5k/dma.c +@@ -854,10 +854,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); ++#else ++ /* WAR for AR71xx PCI bug */ ++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, ++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); ++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, ++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B); ++#endif + } + + /* Pre-enable interrupts on 5211/5212*/ diff --git a/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch b/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch new file mode 100644 index 0000000..1df4aab --- /dev/null +++ b/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch @@ -0,0 +1,46 @@ +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw + goto end; + } + +- /* Don't allow other interfaces if one ad-hoc is configured. +- * TODO: Fix the problems with ad-hoc and multiple other interfaces. +- * We would need to operate the HW in ad-hoc mode to allow TSF updates +- * for the IBSS, but this breaks with additional AP or STA interfaces +- * at the moment. */ +- if (ah->num_adhoc_vifs || +- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { ++ /* Don't allow more than one ad-hoc interface */ ++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) { + ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n"); + ret = -ELNRNG; + goto end; +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -2009,7 +2009,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) + } + + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + +- ah->num_mesh_vifs > 1) || ++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) || + ah->opmode == NL80211_IFTYPE_MESH_POINT) { + u64 tsf = ath5k_hw_get_tsf64(ah); + u32 tsftu = TSF_TO_TU(tsf); +@@ -2095,7 +2095,7 @@ ath5k_beacon_update_timers(struct ath5k_ + + intval = ah->bintval & AR5K_BEACON_PERIOD; + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +- + ah->num_mesh_vifs > 1) { ++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) { + intval /= ATH_BCBUF; /* staggered multi-bss beacons */ + if (intval < 15) + ATH5K_WARN(ah, "intval %u is too low, min 15\n", +@@ -2561,6 +2561,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_MESH_POINT) | + #endif + BIT(NL80211_IFTYPE_AP) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + static const struct ieee80211_iface_combination if_comb = { diff --git a/patches/ath5k/420-ath5k_disable_fast_cc.patch b/patches/ath5k/420-ath5k_disable_fast_cc.patch new file mode 100644 index 0000000..414f495 --- /dev/null +++ b/patches/ath5k/420-ath5k_disable_fast_cc.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + tsf_lo = 0; + mode = 0; + ++#if 0 + /* + * Sanity check for fast flag + * Fast channel change only available +@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + */ + if (fast && (ah->ah_radio != AR5K_RF2413) && + (ah->ah_radio != AR5K_RF5413)) ++#endif + fast = false; + + /* Disable sleep clock operation diff --git a/patches/ath5k/430-add_ath5k_platform.patch b/patches/ath5k/430-add_ath5k_platform.patch new file mode 100644 index 0000000..b213e2a --- /dev/null +++ b/patches/ath5k/430-add_ath5k_platform.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/include/linux/ath5k_platform.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2008 Atheros Communications Inc. ++ * Copyright (c) 2009 Gabor Juhos ++ * Copyright (c) 2009 Imre Kaloz ++ * Copyright (c) 2010 Daniel Golle ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _LINUX_ATH5K_PLATFORM_H ++#define _LINUX_ATH5K_PLATFORM_H ++ ++#define ATH5K_PLAT_EEP_MAX_WORDS 2048 ++ ++struct ath5k_platform_data { ++ u16 *eeprom_data; ++ u8 *macaddr; ++}; ++ ++#endif /* _LINUX_ATH5K_PLATFORM_H */ diff --git a/patches/ath5k/440-ath5k_channel_bw_debugfs.patch b/patches/ath5k/440-ath5k_channel_bw_debugfs.patch new file mode 100644 index 0000000..6ff95f9 --- /dev/null +++ b/patches/ath5k/440-ath5k_channel_bw_debugfs.patch @@ -0,0 +1,142 @@ +This adds a bwmode debugfs file which can be used to set alternate +channel operating bandwidths. Only tested with AR5413 and only at +5 and 20 mhz channels. + +Signed-off-by: Pat Erley +--- +Other devices will need to be added to the switch in write_file_bwmode + +drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ + 1 files changed, 86 insertions(+), 0 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/debug.c ++++ b/drivers/net/wireless/ath/ath5k/debug.c +@@ -803,6 +803,97 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++/* debugfs: bwmode */ ++ ++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[15]; ++ unsigned int len = 0; ++ ++ int cur_ah_bwmode = ah->ah_bwmode_debug; ++ ++#define print_selected(MODE, LABEL) \ ++ if (cur_ah_bwmode == MODE) \ ++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \ ++ else \ ++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \ ++ len += snprintf(buf+len, sizeof(buf)-len, " "); ++ ++ print_selected(AR5K_BWMODE_5MHZ, "5"); ++ print_selected(AR5K_BWMODE_10MHZ, "10"); ++ print_selected(AR5K_BWMODE_DEFAULT, "20"); ++ print_selected(AR5K_BWMODE_40MHZ, "40"); ++#undef print_selected ++ ++ len += snprintf(buf+len, sizeof(buf)-len, "\n"); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_bwmode(struct file *file, ++ const char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[3]; ++ int bw = 20; ++ int tobwmode = AR5K_BWMODE_DEFAULT; ++ ++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) ++ return -EFAULT; ++ ++ /* TODO: Add check for active interface */ ++ ++ if(strncmp(buf, "5", 1) == 0 ) { ++ tobwmode = AR5K_BWMODE_5MHZ; ++ bw = 5; ++ } else if ( strncmp(buf, "10", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_10MHZ; ++ bw = 10; ++ } else if ( strncmp(buf, "20", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_DEFAULT; ++ bw = 20; ++ } else if ( strncmp(buf, "40", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_40MHZ; ++ bw = 40; ++ } else ++ return -EINVAL; ++ ++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n", ++ bw, tobwmode); ++ ++ switch (ah->ah_radio) { ++ /* TODO: only define radios that actually support 5/10mhz channels */ ++ case AR5K_RF5413: ++ case AR5K_RF5110: ++ case AR5K_RF5111: ++ case AR5K_RF5112: ++ case AR5K_RF2413: ++ case AR5K_RF2316: ++ case AR5K_RF2317: ++ case AR5K_RF2425: ++ if(ah->ah_bwmode_debug != tobwmode) { ++ mutex_lock(&ah->lock); ++ ah->ah_bwmode = tobwmode; ++ ah->ah_bwmode_debug = tobwmode; ++ mutex_unlock(&ah->lock); ++ } ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return count; ++} ++ ++static const struct file_operations fops_bwmode = { ++ .read = read_file_bwmode, ++ .write = write_file_bwmode, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; + + /* debugfs: queues etc */ + +@@ -995,6 +1086,8 @@ ath5k_debug_init_device(struct ath5k_hw + debugfs_create_file("queue", 0600, phydir, ah, &fops_queue); + debugfs_create_bool("32khz_clock", 0600, phydir, + &ah->ah_use_32khz_clock); ++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah, ++ &fops_bwmode); + } + + /* functions used in other places */ +--- a/drivers/net/wireless/ath/ath5k/ath5k.h ++++ b/drivers/net/wireless/ath/ath5k/ath5k.h +@@ -1372,6 +1372,7 @@ struct ath5k_hw { + u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; ++ u8 ah_bwmode_debug; + bool ah_short_slot; + + /* Antenna Control */ +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -465,6 +465,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru + return -EINVAL; + } + ++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT) ++ ah->ah_bwmode = ah->ah_bwmode_debug; ++ + /* + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the diff --git a/patches/ath9k/341-wifi-ath9k-obtain-system-gpios.patch b/patches/ath9k/341-wifi-ath9k-obtain-system-gpios.patch new file mode 100644 index 0000000..a14ed55 --- /dev/null +++ b/patches/ath9k/341-wifi-ath9k-obtain-system-gpios.patch @@ -0,0 +1,273 @@ +From patchwork Tue Apr 23 12:12:33 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Linus Walleij +X-Patchwork-Id: 1926515 +Return-Path: + +X-Original-To: incoming@patchwork.ozlabs.org +Delivered-To: patchwork-incoming@legolas.ozlabs.org +Authentication-Results: legolas.ozlabs.org; + dkim=pass (2048-bit key; + unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 + header.s=google header.b=qX99TQMM; + dkim-atps=neutral +Authentication-Results: legolas.ozlabs.org; + spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org + (client-ip=2604:1380:45e3:2400::1; helo=sv.mirrors.kernel.org; + envelope-from=linux-gpio+bounces-5755-incoming=patchwork.ozlabs.org@vger.kernel.org; + receiver=patchwork.ozlabs.org) +Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org + [IPv6:2604:1380:45e3:2400::1]) + (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + key-exchange X25519 server-signature ECDSA (secp384r1)) + (No client certificate requested) + by legolas.ozlabs.org (Postfix) with ESMTPS id 4VP1Gc6RZKz1yZP + for ; Tue, 23 Apr 2024 22:12:56 +1000 (AEST) +Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org + [52.25.139.140]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by sv.mirrors.kernel.org (Postfix) with ESMTPS id 5BB9C28522A + for ; Tue, 23 Apr 2024 12:12:55 +0000 (UTC) +Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) + by smtp.subspace.kernel.org (Postfix) with ESMTP id 2F83B8563D; + Tue, 23 Apr 2024 12:12:41 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org + header.b="qX99TQMM" +X-Original-To: linux-gpio@vger.kernel.org +Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com + [209.85.208.179]) + (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8F3C82865 + for ; Tue, 23 Apr 2024 12:12:37 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=209.85.208.179 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1713874361; cv=none; + b=d6RcvcAu8hBYAK8Io489ZHQpJVXPwuokP6iMcAkbvElCerbXD6jAdqdi+RjDlo5C49GHGO4FQ19UwQn/VE//qSwiK1ulTSBp3OkvAmyb7yYAFnDs9AVNWRw+5/NxeFNn3fj5PyvqVymIbaJKabfrOVNwkz/5JMHxEIJtr6Crmog= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1713874361; c=relaxed/simple; + bh=0eXJ5AIjzz1TBGZ8SlshIPrEHZaZwZfYEdof+dSpu4Y=; + h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; + b=EfFtruUxRIGy+jylEiJ2rPEyPCjGCc8ptT9FVxe6s0O/kW38Y6196xVQeiSV2tSKVCEOIO+9HoqmpgdKsJE7gU9++EcrasP96MYpsklYpc2zsWW3b8QEhfxfZ9Ai/idyYihE2u9dQ7a143P/Ij/twDrZTt24wO/mtHDrE5XcCFI= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=linaro.org; + spf=pass smtp.mailfrom=linaro.org; + dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org + header.b=qX99TQMM; arc=none smtp.client-ip=209.85.208.179 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=linaro.org +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=linaro.org +Received: by mail-lj1-f179.google.com with SMTP id + 38308e7fff4ca-2dd041acff1so40839131fa.1 + for ; + Tue, 23 Apr 2024 05:12:37 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=linaro.org; s=google; t=1713874356; x=1714479156; + darn=vger.kernel.org; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:from:to:cc:subject:date:message-id:reply-to; + bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=; + b=qX99TQMMdHbskFYUaw8c93sIJsUhKmj/WPdyahHcupUhwn5wol4aVoPczkOKYwJZhE + eoInxzjAHIl3UNKyvPPrD4MrbLcSoFT6mTFMsgRQYUghsLattmGcqIebu9XT556dBhsf + DydmpqGgnTOIa+IEknFxg24mo8Xn2LVmDC7LSGEYykUy1xLHd1NSq56YEaYXC7641xeZ + 9TOL0rZszeGld5cCS3013EmEeXQGCC3lAP83Eb48vbFXjPojkN0s40rZ2s8YpVsGT0iP + LeLVtP/E8XJqi4YipKryKSgbgOvQ1Bclle5+s+2qcJQNnSEjekMwR59BIRs3OZH2SRfN + gQdQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1713874356; x=1714479156; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:x-gm-message-state:from:to:cc:subject:date:message-id + :reply-to; + bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=; + b=jEBH4NQ7SzFi2tnb1lgL06IchnBJoscNgKesjlorvou6X/9wDE/VbgxNFKR0zWwdTk + BEjG/ifFJxLmM9jdaCKu5cJc4yiDNXp7yZd48D71V34zJ4aINAGAx4hcOKqf95neFknx + nsFPpBFnTYFEpCLF0TebVoL6h6ehPzSojmkArzsrMppNvW2cwJ5gDlkqy2y4SezLanmM + 6iU0ksnwE0bb2iLkahhgo00Ejt33yqxwa+3xBfhOe9oYKSSZYnY7qVq055SSwt9IAq+H + REGyJN+GrvupTHagiioYe3LPXDPdOui9ZixXXDllw1t1yGUy+TkJu8xSqtvHEfg81FHP + AxtA== +X-Forwarded-Encrypted: i=1; + AJvYcCUbxzPklfPYrLgyY1I0ycuj7Dh04dcGVonYocA2mzxzlAEV107o0ELlFqr3O9Td+tV/t0eV9ly9YAbTY6n1XPnFXS5dsYYAZw6RHw== +X-Gm-Message-State: AOJu0YxsC7zdakTzntbiRFnN2A7yTrR0x+IpR6ce6eGn5kHeqIBi1km+ + zTVpRulbch3JsmzVDbCbbAAYoBkNgEA568YL6zdjVARnvFwNz1cqatOrR1AXUm0= +X-Google-Smtp-Source: + AGHT+IHBRMGvaJM98f86Z6m/RfVhK2XejjNGF3EvcRq/4x3oGM0DKpd2PbeCJdgmzHjLPVVbdsNzJg== +X-Received: by 2002:a2e:9852:0:b0:2d8:a98d:18e with SMTP id + e18-20020a2e9852000000b002d8a98d018emr7955886ljj.8.1713874355700; + Tue, 23 Apr 2024 05:12:35 -0700 (PDT) +Received: from [192.168.1.140] ([85.235.12.238]) + by smtp.gmail.com with ESMTPSA id + x6-20020a2e7c06000000b002da179d8d25sm1628982ljc.64.2024.04.23.05.12.33 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Tue, 23 Apr 2024 05:12:35 -0700 (PDT) +From: Linus Walleij +Date: Tue, 23 Apr 2024 14:12:33 +0200 +Subject: [PATCH v2] wifi: ath9k: Obtain system GPIOS from descriptors +Precedence: bulk +X-Mailing-List: linux-gpio@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Message-Id: <20240423-descriptors-wireless-v2-1-6d1d03b30bfa@linaro.org> +X-B4-Tracking: v=1; b=H4sIALClJ2YC/22Nyw6CMBBFf4XM2hpanrLyPwyL0o4wCaFkxqCG9 + N+txKXLc5Nz7g6CTCjQZTswbiQUlgTmlIGb7DKiIp8YTG7KXBujPIpjWh+BRT2JcUYRNbTeXir + v7FBUkNSV8U6vI3vrE08kSXgfL5v+rr9gof8HN61yhdo1rvJ125T1dabFcjgHHqGPMX4Ao4iiN + LkAAAA= +To: Kalle Valo , + Andy Shevchenko , + Arnd Bergmann , Alban Bedel , + Bartosz Golaszewski , =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rg?= + =?utf-8?q?ensen?= +Cc: linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com, + linux-gpio@vger.kernel.org, Linus Walleij +X-Mailer: b4 0.13.0 + +The ath9k has an odd use of system-wide GPIOs: if the chip +does not have internal GPIO capability, it will try to obtain a +GPIO line from the system GPIO controller: + + if (BIT(gpio) & ah->caps.gpio_mask) + ath9k_hw_gpio_cfg_wmac(...); + else if (AR_SREV_SOC(ah)) + ath9k_hw_gpio_cfg_soc(ah, gpio, out, label); + +Where ath9k_hw_gpio_cfg_soc() will attempt to issue +gpio_request_one() passing the local GPIO number of the controller +(0..31) to gpio_request_one(). + +This is somewhat peculiar and possibly even dangerous: there is +nowadays no guarantee of the numbering of these system-wide +GPIOs, and assuming that GPIO 0..31 as used by ath9k would +correspond to GPIOs 0..31 on the system as a whole seems a bit +wild. + +Register all 32 GPIOs at index 0..31 directly in the ATH79K +GPIO driver and associate with WIFI if and only if we are probing +ATH79K wifi from the AHB bus (used for SoCs). + +Signed-off-by: Linus Walleij +--- +Changes in v2: +- Define all the descriptors directly in the ATH79K + GPIO driver in case the driver want to request them directly. +- Link to v1: https://lore.kernel.org/r/20240131-descriptors-wireless-v1-0-e1c7c5d68746@linaro.org +--- + drivers/net/wireless/ath/ath9k/hw.c | 29 ++++++++++++----------- + drivers/net/wireless/ath/ath9k/hw.h | 3 ++- + 2 files changed, 32 insertions(+), 15 deletions(-) + + +--- +base-commit: 4cece764965020c22cff7665b18a012006359095 +change-id: 20240122-descriptors-wireless-b8da95dcab35 + +Best regards, + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -20,7 +20,7 @@ + #include + #include + #include +-#include ++#include + #include + + #include "hw.h" +@@ -2718,19 +2718,25 @@ static void ath9k_hw_gpio_cfg_output_mux + static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out, + const char *label) + { ++ enum gpiod_flags flags = out ? GPIOD_OUT_LOW : GPIOD_IN; ++ struct gpio_desc *gpiod; + int err; + +- if (ah->caps.gpio_requested & BIT(gpio)) ++ if (ah->gpiods[gpio]) + return; + +- err = devm_gpio_request_one(ah->dev, gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label); +- if (err) { ++ /* Obtains a system specific GPIO descriptor from another GPIO controller */ ++ gpiod = gpiod_get_index(NULL, "ath9k", gpio, flags); ++ ++ if (IS_ERR(gpiod)) { ++ err = PTR_ERR(gpiod); + ath_err(ath9k_hw_common(ah), "request GPIO%d failed:%d\n", + gpio, err); + return; + } + +- ah->caps.gpio_requested |= BIT(gpio); ++ gpiod_set_consumer_name(gpiod, label); ++ ah->gpiods[gpio] = gpiod; + } + + static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out, +@@ -2792,8 +2798,10 @@ void ath9k_hw_gpio_free(struct ath_hw *a + + WARN_ON(gpio >= ah->caps.num_gpio_pins); + +- if (ah->caps.gpio_requested & BIT(gpio)) +- ah->caps.gpio_requested &= ~BIT(gpio); ++ if (ah->gpiods[gpio]) { ++ gpiod_put(ah->gpiods[gpio]); ++ ah->gpiods[gpio] = NULL; ++ } + } + EXPORT_SYMBOL(ath9k_hw_gpio_free); + +@@ -2821,8 +2829,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, + val = REG_READ(ah, AR_GPIO_IN(ah)) & BIT(gpio); + else + val = MS_REG_READ(AR, gpio); +- } else if (BIT(gpio) & ah->caps.gpio_requested) { +- val = gpio_get_value(gpio) & BIT(gpio); ++ } else if (ah->gpiods[gpio]) { ++ val = gpiod_get_value(ah->gpiods[gpio]); + } else { + WARN_ON(1); + } +@@ -2845,8 +2853,8 @@ void ath9k_hw_set_gpio(struct ath_hw *ah + AR7010_GPIO_OUT : AR_GPIO_IN_OUT(ah); + + REG_RMW(ah, out_addr, val << gpio, BIT(gpio)); +- } else if (BIT(gpio) & ah->caps.gpio_requested) { +- gpio_set_value(gpio, val); ++ } else if (ah->gpiods[gpio]) { ++ gpiod_set_value(ah->gpiods[gpio], val); + } else { + WARN_ON(1); + } +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -19,6 +19,7 @@ + + #include + #include ++#include + #include + #include + +@@ -302,7 +303,6 @@ struct ath9k_hw_capabilities { + u8 max_rxchains; + u8 num_gpio_pins; + u32 gpio_mask; +- u32 gpio_requested; + u8 rx_hp_qdepth; + u8 rx_lp_qdepth; + u8 rx_status_len; +@@ -783,6 +783,7 @@ struct ath_hw { + struct ath9k_hw_capabilities caps; + struct ath9k_channel channels[ATH9K_NUM_CHANNELS]; + struct ath9k_channel *curchan; ++ struct gpio_desc *gpiods[32]; + + union { + struct ar5416_eeprom_def def; diff --git a/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch new file mode 100644 index 0000000..3a0171d --- /dev/null +++ b/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Sat, 9 Jul 2016 15:25:24 +0200 +Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx + +Should fix a few stability issues + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1434,8 +1434,12 @@ static bool ath9k_hw_set_reset(struct at + if (!AR_SREV_9100(ah)) + REG_WRITE(ah, AR_RC, 0); + +- if (AR_SREV_9100(ah)) ++ if (AR_SREV_9100(ah)) { ++ /* Reset the AHB-WMAC interface */ ++ if (ah->external_reset) ++ ah->external_reset(); + udelay(50); ++ } + + return true; + } diff --git a/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch b/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch new file mode 100644 index 0000000..aac7e13 --- /dev/null +++ b/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch @@ -0,0 +1,129 @@ +From: Felix Fietkau +Date: Sat, 9 Jul 2016 15:26:44 +0200 +Subject: [PATCH] ath9k_hw: issue external reset for QCA955x + +The RTC interface on the SoC needs to be reset along with the rest of +the WMAC. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1311,39 +1311,56 @@ void ath9k_hw_get_delta_slope_vals(struc + *coef_exponent = coef_exp - 16; + } + +-/* AR9330 WAR: +- * call external reset function to reset WMAC if: +- * - doing a cold reset +- * - we have pending frames in the TX queues. +- */ +-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) ++static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type) + { +- int i, npend = 0; ++ int i; + +- for (i = 0; i < AR_NUM_QCU; i++) { +- npend = ath9k_hw_numtxpending(ah, i); +- if (npend) +- break; +- } +- +- if (ah->external_reset && +- (npend || type == ATH9K_RESET_COLD)) { +- int reset_err = 0; +- +- ath_dbg(ath9k_hw_common(ah), RESET, +- "reset MAC via external reset\n"); +- +- reset_err = ah->external_reset(); +- if (reset_err) { +- ath_err(ath9k_hw_common(ah), +- "External reset failed, err=%d\n", +- reset_err); +- return false; ++ if (type == ATH9K_RESET_COLD) ++ return true; ++ ++ if (AR_SREV_9550(ah)) ++ return true; ++ ++ /* AR9330 WAR: ++ * call external reset function to reset WMAC if: ++ * - doing a cold reset ++ * - we have pending frames in the TX queues. ++ */ ++ if (AR_SREV_9330(ah)) { ++ for (i = 0; i < AR_NUM_QCU; i++) { ++ if (ath9k_hw_numtxpending(ah, i)) ++ return true; + } ++ } ++ ++ return false; ++} ++ ++static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) ++{ ++ int err; ++ ++ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) ++ return true; ++ ++ ath_dbg(ath9k_hw_common(ah), RESET, ++ "reset MAC via external reset\n"); + +- REG_WRITE(ah, AR_RTC_RESET(ah), 1); ++ err = ah->external_reset(); ++ if (err) { ++ ath_err(ath9k_hw_common(ah), ++ "External reset failed, err=%d\n", err); ++ return false; + } + ++ if (AR_SREV_9550(ah)) { ++ REG_WRITE(ah, AR_RTC_RESET(ah), 0); ++ udelay(10); ++ } ++ ++ REG_WRITE(ah, AR_RTC_RESET(ah), 1); ++ udelay(10); ++ + return true; + } + +@@ -1396,24 +1413,24 @@ static bool ath9k_hw_set_reset(struct at + rst_flags |= AR_RTC_RC_MAC_COLD; + } + +- if (AR_SREV_9330(ah)) { +- if (!ath9k_hw_ar9330_reset_war(ah, type)) +- return false; +- } +- + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_check_gpm_offset(ah); + + /* DMA HALT added to resolve ar9300 and ar9580 bus error during +- * RTC_RC reg read ++ * RTC_RC reg read. Also needed for AR9550 external reset + */ +- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { ++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { + REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, + 20 * AH_WAIT_TIMEOUT); +- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + } + ++ if (!AR_SREV_9100(ah)) ++ ath9k_hw_external_reset(ah, type); ++ ++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) ++ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); ++ + REG_WRITE(ah, AR_RTC_RC(ah), rst_flags); + + REGWRITE_BUFFER_FLUSH(ah); diff --git a/patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch b/patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch new file mode 100644 index 0000000..8aaccf4 --- /dev/null +++ b/patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch @@ -0,0 +1,35 @@ +From: Felix Fietkau +Date: Sun, 7 Jun 2015 13:53:35 +0200 +Subject: [PATCH] ath9k: force rx_clear when disabling rx + +This makes stopping Rx more reliable and should reduce the frequency of +Rx related DMA stop warnings. Don't use rx_clear in TX99 mode. + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Helmut Schaa +--- + +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -678,13 +678,18 @@ void ath9k_hw_startpcureceive(struct ath + + ath9k_ani_reset(ah, is_scanning); + +- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); ++ REG_CLR_BIT(ah, AR_DIAG_SW, ++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + } + EXPORT_SYMBOL(ath9k_hw_startpcureceive); + + void ath9k_hw_abortpcurecv(struct ath_hw *ah) + { +- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); ++ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT; ++ ++ if (!IS_ENABLED(CPTCFG_ATH9K_TX99)) ++ reg |= AR_DIAG_FORCE_RX_CLEAR; ++ REG_SET_BIT(ah, AR_DIAG_SW, reg); + + ath9k_hw_disable_mib_counters(ah); + } diff --git a/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch new file mode 100644 index 0000000..5cb891e --- /dev/null +++ b/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch @@ -0,0 +1,36 @@ +From: Felix Fietkau +Date: Sat, 14 May 2016 14:51:02 +0200 +Subject: [PATCH] Revert "ath9k: interpret requested txpower in EIRP + domain" + +This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411. +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2974,7 +2974,8 @@ void ath9k_hw_apply_txpower(struct ath_h + { + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); + struct ieee80211_channel *channel; +- int chan_pwr, new_pwr; ++ int chan_pwr, new_pwr, max_gain; ++ int ant_gain, ant_reduction = 0; + u16 ctl = NO_CTL; + + if (!chan) +@@ -2986,9 +2987,14 @@ void ath9k_hw_apply_txpower(struct ath_h + channel = chan->chan; + chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER); + new_pwr = min_t(int, chan_pwr, reg->power_limit); ++ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; ++ ++ ant_gain = get_antenna_gain(ah, chan); ++ if (ant_gain > max_gain) ++ ant_reduction = ant_gain - max_gain; + + ah->eep_ops->set_txpower(ah, chan, ctl, +- get_antenna_gain(ah, chan), new_pwr, test); ++ ant_reduction, new_pwr, test); + } + + void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) diff --git a/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch new file mode 100644 index 0000000..14abb40 --- /dev/null +++ b/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Wed, 19 Jul 2017 08:49:31 +0200 +Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory + domain + +FCC regulatory rules allow for up to 6 dBi antenna gain. Account for +this in the EEPROM based tx power reduction code. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2993,6 +2993,10 @@ void ath9k_hw_apply_txpower(struct ath_h + if (ant_gain > max_gain) + ant_reduction = ant_gain - max_gain; + ++ /* FCC allows maximum antenna gain of 6 dBi */ ++ if (reg->region == NL80211_DFS_FCC) ++ ant_reduction = max_t(int, ant_reduction - 12, 0); ++ + ah->eep_ops->set_txpower(ah, chan, ctl, + ant_reduction, new_pwr, test); + } diff --git a/patches/ath9k/401-ath9k_blink_default.patch b/patches/ath9k/401-ath9k_blink_default.patch new file mode 100644 index 0000000..7405e59 --- /dev/null +++ b/patches/ath9k/401-ath9k_blink_default.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -47,7 +47,7 @@ int ath9k_modparam_nohwcrypt; + module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); + MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +-int ath9k_led_blink; ++int ath9k_led_blink = 1; + module_param_named(blink, ath9k_led_blink, int, 0444); + MODULE_PARM_DESC(blink, "Enable LED blink on activity"); + diff --git a/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch b/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch new file mode 100644 index 0000000..978d915 --- /dev/null +++ b/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -836,6 +836,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_AP) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT diff --git a/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch b/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch new file mode 100644 index 0000000..dffeb32 --- /dev/null +++ b/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch @@ -0,0 +1,34 @@ +From d946085ff5a331de64e91a2e3c96b9ca79d740f5 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 15 Jun 2020 00:10:34 +0200 +Subject: [PATCH] ath9k: enabled MFP capability unconditionally + +ath9k will already fallback on software-crypto for chipsets not +supporting IEEE802.11w (MFP). So advertising MFP is not dependent +on disabling HW crypto for all traffic entirely. + +Signed-off-by: David Bauer +--- + drivers/net/wireless/ath/ath9k/init.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -917,6 +917,7 @@ static void ath9k_set_hw_capab(struct at + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ++ ieee80211_hw_set(hw, MFP_CAPABLE); + + if (ath9k_ps_enable) + ieee80211_hw_set(hw, SUPPORTS_PS); +@@ -929,9 +930,6 @@ static void ath9k_set_hw_capab(struct at + IEEE80211_RADIOTAP_MCS_HAVE_STBC; + } + +- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) +- ieee80211_hw_set(hw, MFP_CAPABLE); +- + hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_P2P_GO_CTWIN; diff --git a/patches/ath9k/500-ath9k_eeprom_debugfs.patch b/patches/ath9k/500-ath9k_eeprom_debugfs.patch new file mode 100644 index 0000000..8c139ac --- /dev/null +++ b/patches/ath9k/500-ath9k_eeprom_debugfs.patch @@ -0,0 +1,92 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1430,6 +1430,7 @@ int ath9k_init_debug(struct ath_hw *ah) + + ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); + ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); ++ ath9k_cmn_debug_eeprom(sc->debug.debugfs_phy, sc->sc_ah); + + debugfs_create_u32("gpio_mask", 0600, + sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); +--- a/drivers/net/wireless/ath/ath9k/common-debug.c ++++ b/drivers/net/wireless/ath/ath9k/common-debug.c +@@ -260,3 +260,58 @@ void ath9k_cmn_debug_phy_err(struct dent + &fops_phy_err); + } + EXPORT_SYMBOL(ath9k_cmn_debug_phy_err); ++ ++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_hw *ah = file->private_data; ++ struct ath_common *common = ath9k_hw_common(ah); ++ int bytes = 0; ++ int pos = *ppos; ++ int size = 4096; ++ u16 val; ++ int i; ++ ++ if (AR_SREV_9300_20_OR_LATER(ah)) ++ size = 16384; ++ ++ if (*ppos < 0) ++ return -EINVAL; ++ ++ if (count > size - *ppos) ++ count = size - *ppos; ++ ++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) { ++ void *from = &val; ++ ++ if (!common->bus_ops->eeprom_read(common, i, &val)) ++ val = 0xffff; ++ ++ if (*ppos % 2) { ++ from++; ++ bytes = 1; ++ } else if (count == 1) { ++ bytes = 1; ++ } else { ++ bytes = 2; ++ } ++ if (copy_to_user(user_buf, from, bytes)) ++ return -EFAULT; ++ user_buf += bytes; ++ } ++ return *ppos - pos; ++} ++ ++static const struct file_operations fops_eeprom = { ++ .read = read_file_eeprom, ++ .open = simple_open, ++ .owner = THIS_MODULE ++}; ++ ++void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy, ++ struct ath_hw *ah) ++{ ++ debugfs_create_file("eeprom", S_IRUSR, debugfs_phy, ah, ++ &fops_eeprom); ++} ++EXPORT_SYMBOL(ath9k_cmn_debug_eeprom); +--- a/drivers/net/wireless/ath/ath9k/common-debug.h ++++ b/drivers/net/wireless/ath/ath9k/common-debug.h +@@ -69,6 +69,8 @@ void ath9k_cmn_debug_modal_eeprom(struct + struct ath_hw *ah); + void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, + struct ath_hw *ah); ++void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy, ++ struct ath_hw *ah); + void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, + struct ath_rx_status *rs); + void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, +--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +@@ -512,6 +512,7 @@ int ath9k_htc_init_debug(struct ath_hw * + + ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah); + ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah); ++ ath9k_cmn_debug_eeprom(priv->debug.debugfs_phy, priv->ah); + + return 0; + } diff --git a/patches/ath9k/501-ath9k_ahb_init.patch b/patches/ath9k/501-ath9k_ahb_init.patch new file mode 100644 index 0000000..2aee171 --- /dev/null +++ b/patches/ath9k/501-ath9k_ahb_init.patch @@ -0,0 +1,34 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1132,25 +1132,25 @@ static int __init ath9k_init(void) + { + int error; + +- error = ath_pci_init(); ++ error = ath_ahb_init(); + if (error < 0) { +- pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; + goto err_out; + } + +- error = ath_ahb_init(); ++ error = ath_pci_init(); + if (error < 0) { ++ pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; +- goto err_pci_exit; ++ goto err_ahb_exit; + } + + dmi_check_system(ath9k_quirks); + + return 0; + +- err_pci_exit: +- ath_pci_exit(); ++ err_ahb_exit: ++ ath_ahb_exit(); + err_out: + return error; + } diff --git a/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch b/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch new file mode 100644 index 0000000..fda050a --- /dev/null +++ b/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -402,13 +402,8 @@ static void ath9k_hw_init_config(struct + + ah->config.rx_intr_mitigation = true; + +- if (AR_SREV_9300_20_OR_LATER(ah)) { +- ah->config.rimt_last = 500; +- ah->config.rimt_first = 2000; +- } else { +- ah->config.rimt_last = 250; +- ah->config.rimt_first = 700; +- } ++ ah->config.rimt_last = 250; ++ ah->config.rimt_first = 500; + + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->config.pll_pwrsave = 7; diff --git a/patches/ath9k/511-ath9k_reduce_rxbuf.patch b/patches/ath9k/511-ath9k_reduce_rxbuf.patch new file mode 100644 index 0000000..d806782 --- /dev/null +++ b/patches/ath9k/511-ath9k_reduce_rxbuf.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc * + (_l) &= ((_sz) - 1); \ + } while (0) + +-#define ATH_RXBUF 512 ++#define ATH_RXBUF 256 + #define ATH_TXBUF 512 + #define ATH_TXBUF_RESERVE 5 + #define ATH_TXMAXTRY 13 diff --git a/patches/ath9k/512-ath9k_channelbw_debugfs.patch b/patches/ath9k/512-ath9k_channelbw_debugfs.patch new file mode 100644 index 0000000..9a60631 --- /dev/null +++ b/patches/ath9k/512-ath9k_channelbw_debugfs.patch @@ -0,0 +1,191 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1431,6 +1431,7 @@ int ath9k_init_debug(struct ath_hw *ah) + ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); + ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); + ath9k_cmn_debug_eeprom(sc->debug.debugfs_phy, sc->sc_ah); ++ ath9k_cmn_debug_chanbw(sc->debug.debugfs_phy, sc->sc_ah); + + debugfs_create_u32("gpio_mask", 0600, + sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -151,6 +151,7 @@ struct ath_common { + int debug_mask; + enum ath_device_state state; + unsigned long op_flags; ++ u32 chan_bw; + + struct ath_ani ani; + +@@ -181,6 +182,7 @@ struct ath_common { + const struct ath_ops *ops; + const struct ath_bus_ops *bus_ops; + const struct ath_ps_ops *ps_ops; ++ const struct ieee80211_ops *ieee_ops; + + bool btcoex_enabled; + bool disable_ani; +--- a/drivers/net/wireless/ath/ath9k/common.c ++++ b/drivers/net/wireless/ath/ath9k/common.c +@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke + /* + * Update internal channel flags. + */ +-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ++static void ath9k_cmn_update_ichannel(struct ath_common *common, ++ struct ath9k_channel *ichan, + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *chan = chandef->chan; + u16 flags = 0; ++ int width; + + ichan->channel = chan->center_freq; + ichan->chan = chan; +@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st + if (chan->band == NL80211_BAND_5GHZ) + flags |= CHANNEL_5GHZ; + +- switch (chandef->width) { ++ switch (common->chan_bw) { ++ case 5: ++ width = NL80211_CHAN_WIDTH_5; ++ break; ++ case 10: ++ width = NL80211_CHAN_WIDTH_10; ++ break; ++ default: ++ width = chandef->width; ++ break; ++ } ++ ++ switch (width) { + case NL80211_CHAN_WIDTH_5: + flags |= CHANNEL_QUARTER; + break; +@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *curchan = chandef->chan; ++ struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *channel; + + channel = &ah->channels[curchan->hw_value]; +- ath9k_cmn_update_ichannel(channel, chandef); ++ ath9k_cmn_update_ichannel(common, channel, chandef); + + return channel; + } +--- a/drivers/net/wireless/ath/ath9k/common-debug.c ++++ b/drivers/net/wireless/ath/ath9k/common-debug.c +@@ -315,3 +315,55 @@ void ath9k_cmn_debug_eeprom(struct dentr + &fops_eeprom); + } + EXPORT_SYMBOL(ath9k_cmn_debug_eeprom); ++ ++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_hw *ah = file->private_data; ++ struct ath_common *common = ath9k_hw_common(ah); ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08x\n", common->chan_bw); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_hw *ah = file->private_data; ++ struct ath_common *common = ath9k_hw_common(ah); ++ unsigned long chan_bw; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &chan_bw)) ++ return -EINVAL; ++ ++ common->chan_bw = chan_bw; ++ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) ++ common->ieee_ops->config(ah->hw, IEEE80211_CONF_CHANGE_CHANNEL); ++ ++ return count; ++} ++ ++static const struct file_operations fops_chanbw = { ++ .read = read_file_chan_bw, ++ .write = write_file_chan_bw, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++void ath9k_cmn_debug_chanbw(struct dentry *debugfs_phy, ++ struct ath_hw *ah) ++{ ++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, debugfs_phy, ah, ++ &fops_chanbw); ++} ++EXPORT_SYMBOL(ath9k_cmn_debug_chanbw); +--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +@@ -513,6 +513,7 @@ int ath9k_htc_init_debug(struct ath_hw * + ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah); + ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah); + ath9k_cmn_debug_eeprom(priv->debug.debugfs_phy, priv->ah); ++ ath9k_cmn_debug_chanbw(priv->debug.debugfs_phy, priv->ah); + + return 0; + } +--- a/drivers/net/wireless/ath/ath9k/common-debug.h ++++ b/drivers/net/wireless/ath/ath9k/common-debug.h +@@ -71,6 +71,8 @@ void ath9k_cmn_debug_base_eeprom(struct + struct ath_hw *ah); + void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy, + struct ath_hw *ah); ++void ath9k_cmn_debug_chanbw(struct dentry *debugfs_phy, ++ struct ath_hw *ah); + void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, + struct ath_rx_status *rs); + void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, +--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c +@@ -631,6 +631,7 @@ static int ath9k_init_priv(struct ath9k_ + priv->ah = ah; + + common = ath9k_hw_common(ah); ++ common->ieee_ops = &ath9k_htc_ops; + common->ops = &ah->reg_ops; + common->ps_ops = &ath9k_htc_ps_ops; + common->bus_ops = &ath9k_usb_bus_ops; +@@ -746,9 +747,9 @@ static void ath9k_set_hw_capab(struct at + + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | +- WIPHY_FLAG_HAS_CHANNEL_SWITCH; +- +- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; ++ WIPHY_FLAG_HAS_CHANNEL_SWITCH | ++ WIPHY_FLAG_SUPPORTS_5_10_MHZ | ++ WIPHY_FLAG_SUPPORTS_TDLS; + + hw->queues = 4; + hw->max_listen_interval = 1; +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -691,6 +691,7 @@ static int ath9k_init_softc(u16 devid, s + if (!ath9k_is_chanctx_enabled()) + sc->cur_chan->hw_queue_base = 0; + ++ common->ieee_ops = &ath9k_ops; + common->ops = &ah->reg_ops; + common->bus_ops = bus_ops; + common->ps_ops = &ath9k_ps_ops; diff --git a/patches/ath9k/513-ath9k_add_pci_ids.patch b/patches/ath9k/513-ath9k_add_pci_ids.patch new file mode 100644 index 0000000..9e3f867 --- /dev/null +++ b/patches/ath9k/513-ath9k_add_pci_ids.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -662,6 +662,7 @@ int ath9k_hw_init(struct ath_hw *ah) + + /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ + switch (ah->hw_version.devid) { ++ case AR9300_DEVID_INVALID: + case AR5416_DEVID_PCI: + case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -37,6 +37,7 @@ + + #define ATHEROS_VENDOR_ID 0x168c + ++#define AR9300_DEVID_INVALID 0xabcd + #define AR5416_DEVID_PCI 0x0023 + #define AR5416_DEVID_PCIE 0x0024 + #define AR9160_DEVID_PCI 0x0027 +--- a/drivers/net/wireless/ath/ath9k/pci.c ++++ b/drivers/net/wireless/ath/ath9k/pci.c +@@ -772,6 +772,7 @@ static const struct pci_device_id ath_pc + .driver_data = ATH9K_PCI_BT_ANT_DIV }, + #endif + ++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */ + { 0 } + }; + diff --git a/patches/ath9k/530-ath9k_extra_leds.patch b/patches/ath9k/530-ath9k_extra_leds.patch new file mode 100644 index 0000000..b92c198 --- /dev/null +++ b/patches/ath9k/530-ath9k_extra_leds.patch @@ -0,0 +1,267 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru + #ifdef CPTCFG_MAC80211_LEDS + void ath_init_leds(struct ath_softc *sc); + void ath_deinit_leds(struct ath_softc *sc); ++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name, ++ const char *trigger, bool active_low); ++ + #else + static inline void ath_init_leds(struct ath_softc *sc) + { +@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc + + #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ + ++struct ath_led { ++ struct list_head list; ++ struct ath_softc *sc; ++ const struct gpio_led *gpio; ++ struct led_classdev cdev; ++}; ++ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +@@ -1035,9 +1045,8 @@ struct ath_softc { + spinlock_t chan_lock; + + #ifdef CPTCFG_MAC80211_LEDS +- bool led_registered; +- char led_name[32]; +- struct led_classdev led_cdev; ++ const char *led_default_trigger; ++ struct list_head leds; + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_ + else + ah->led_pin = ATH_LED_PIN_DEF; + } ++} ++ ++static void ath_led_brightness(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev); ++ struct ath_softc *sc = led->sc; ++ ++ ath9k_ps_wakeup(sc); ++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio, ++ (brightness != LED_OFF) ^ led->gpio->active_low); ++ ath9k_ps_restore(sc); ++} ++ ++static int ath_add_led(struct ath_softc *sc, struct ath_led *led) ++{ ++ const struct gpio_led *gpio = led->gpio; ++ int ret; ++ ++ led->cdev.name = gpio->name; ++ led->cdev.default_trigger = gpio->default_trigger; ++ led->cdev.brightness_set = ath_led_brightness; ++ ++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev); ++ if (ret < 0) ++ return ret; ++ ++ led->sc = sc; ++ list_add(&led->list, &sc->leds); + + /* Configure gpio for output */ +- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", ++ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + +- /* LED off, active low */ +- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); ++ /* LED off */ ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ ++ return 0; + } + +-static void ath_led_brightness(struct led_classdev *led_cdev, +- enum led_brightness brightness) ++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name, ++ const char *trigger, bool active_low) + { +- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); +- u32 val = (brightness == LED_OFF); ++ struct ath_led *led; ++ struct gpio_led *gpio; ++ char *_name; ++ int ret; + +- if (sc->sc_ah->config.led_active_high) +- val = !val; ++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1, ++ GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio = (struct gpio_led *) (led + 1); ++ _name = (char *) (led->gpio + 1); ++ ++ strcpy(_name, name); ++ gpio->name = _name; ++ gpio->gpio = gpio_num; ++ gpio->active_low = active_low; ++ gpio->default_trigger = trigger; ++ ++ ret = ath_add_led(sc, led); ++ if (unlikely(ret < 0)) ++ kfree(led); + +- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); ++ return ret; + } + + void ath_deinit_leds(struct ath_softc *sc) + { +- if (!sc->led_registered) +- return; ++ struct ath_led *led; + +- ath_led_brightness(&sc->led_cdev, LED_OFF); +- led_classdev_unregister(&sc->led_cdev); +- +- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); ++ while (!list_empty(&sc->leds)) { ++ led = list_first_entry(&sc->leds, struct ath_led, list); ++ list_del(&led->list); ++ ath_led_brightness(&led->cdev, LED_OFF); ++ led_classdev_unregister(&led->cdev); ++ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); ++ kfree(led); ++ } + } + + void ath_init_leds(struct ath_softc *sc) + { +- int ret; ++ char led_name[32]; ++ const char *trigger; ++ ++ INIT_LIST_HEAD(&sc->leds); + + if (AR_SREV_9100(sc->sc_ah)) + return; + + ath_fill_led_pin(sc); + +- if (!ath9k_led_blink) +- sc->led_cdev.default_trigger = +- ieee80211_get_radio_led_name(sc->hw); +- +- snprintf(sc->led_name, sizeof(sc->led_name), +- "ath9k-%s", wiphy_name(sc->hw->wiphy)); +- sc->led_cdev.name = sc->led_name; +- sc->led_cdev.brightness_set = ath_led_brightness; ++ snprintf(led_name, sizeof(led_name), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); + +- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); +- if (ret < 0) +- return; ++ if (ath9k_led_blink) ++ trigger = sc->led_default_trigger; ++ else ++ trigger = ieee80211_get_radio_led_name(sc->hw); + +- sc->led_registered = true; ++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, ++ !sc->sc_ah->config.led_active_high); + } + #endif + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1043,7 +1043,7 @@ int ath9k_init_device(u16 devid, struct + + #ifdef CPTCFG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ +- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, ++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, + ARRAY_SIZE(ath9k_tpt_blink)); + #endif +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -123,6 +123,61 @@ static const struct file_operations fops + + #define DMA_BUF_LEN 1024 + ++#ifdef CONFIG_MAC80211_LEDS ++ ++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ char buf[32], *str, *name, *c; ++ ssize_t len; ++ unsigned int gpio; ++ bool active_low = false; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, ubuf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ name = strchr(buf, ','); ++ if (!name) ++ return -EINVAL; ++ ++ *(name++) = 0; ++ if (!*name) ++ return -EINVAL; ++ ++ c = strchr(name, '\n'); ++ if (c) ++ *c = 0; ++ ++ str = buf; ++ if (*str == '!') { ++ str++; ++ active_low = true; ++ } ++ ++ if (kstrtouint(str, 0, &gpio) < 0) ++ return -EINVAL; ++ ++ if (gpio >= sc->sc_ah->caps.num_gpio_pins) ++ return -EINVAL; ++ ++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static const struct file_operations fops_gpio_led = { ++ .write = write_file_gpio_led, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++#endif ++ + + static ssize_t read_file_ani(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +@@ -1391,6 +1446,10 @@ int ath9k_init_debug(struct ath_hw *ah) + ath9k_tx99_init_debug(sc); + ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); + ++#ifdef CONFIG_MAC80211_LEDS ++ debugfs_create_file("gpio_led", S_IWUSR, ++ sc->debug.debugfs_phy, sc, &fops_gpio_led); ++#endif + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/patches/ath9k/540-ath9k_reduce_ani_interval.patch b/patches/ath9k/540-ath9k_reduce_ani_interval.patch new file mode 100644 index 0000000..e899903 --- /dev/null +++ b/patches/ath9k/540-ath9k_reduce_ani_interval.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ani.h ++++ b/drivers/net/wireless/ath/ath9k/ani.h +@@ -42,7 +42,7 @@ + #define ATH9K_ANI_PERIOD 300 + + /* in ms */ +-#define ATH9K_ANI_POLLINTERVAL 1000 ++#define ATH9K_ANI_POLLINTERVAL 300 + + #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 + #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 diff --git a/patches/ath9k/542-ath9k_debugfs_diag.patch b/patches/ath9k/542-ath9k_debugfs_diag.patch new file mode 100644 index 0000000..4b8834a --- /dev/null +++ b/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -0,0 +1,139 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1429,6 +1429,50 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } + ++static ssize_t read_file_diag(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08lx\n", ah->diag); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_diag(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ unsigned long diag; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &diag)) ++ return -EINVAL; ++ ++ ah->diag = diag; ++ ath9k_hw_update_diag(ah); ++ ++ return count; ++} ++ ++static const struct file_operations fops_diag = { ++ .read = read_file_diag, ++ .write = write_file_diag, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1450,6 +1494,8 @@ int ath9k_init_debug(struct ath_hw *ah) + debugfs_create_file("gpio_led", S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_gpio_led); + #endif ++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_diag); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -522,6 +522,12 @@ enum { + ATH9K_RESET_COLD, + }; + ++enum { ++ ATH_DIAG_DISABLE_RX, ++ ATH_DIAG_DISABLE_TX, ++ ATH_DIAG_TRIGGER_ERROR, ++}; ++ + struct ath9k_hw_version { + u32 magic; + u16 devid; +@@ -811,6 +817,8 @@ struct ath_hw { + u32 ah_flags; + s16 nf_override; + ++ unsigned long diag; ++ + bool reset_power_on; + bool htc_reset_init; + +@@ -1080,6 +1088,7 @@ void ath9k_hw_check_nav(struct ath_hw *a + bool ath9k_hw_check_alive(struct ath_hw *ah); + + bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); ++void ath9k_hw_update_diag(struct ath_hw *ah); + + /* Generic hw timer primitives */ + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1872,6 +1872,20 @@ u32 ath9k_hw_get_tsf_offset(ktime_t last + } + EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); + ++void ath9k_hw_update_diag(struct ath_hw *ah) ++{ ++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ ++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++} ++EXPORT_SYMBOL(ath9k_hw_update_diag); ++ + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + struct ath9k_hw_cal_data *caldata, bool fastcc) + { +@@ -2080,6 +2094,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ar9003_hw_disable_phy_restart(ah); + + ath9k_hw_apply_gpio_override(ah); ++ ath9k_hw_update_diag(ah); + + if (AR_SREV_9565(ah) && common->bt_ant_diversity) + REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -537,6 +537,11 @@ irqreturn_t ath_isr(int irq, void *dev) + return IRQ_HANDLED; + } + ++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) { ++ status |= ATH9K_INT_FATAL; ++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag); ++ } ++ + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). diff --git a/patches/ath9k/543-ath9k_entropy_from_adc.patch b/patches/ath9k/543-ath9k_entropy_from_adc.patch new file mode 100644 index 0000000..8966cca --- /dev/null +++ b/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -0,0 +1,186 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -723,6 +723,7 @@ struct ath_spec_scan { + * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + * ++ * @get_adc_entropy: get entropy from the raw ADC I/Q output + * @spectral_scan_config: set parameters for spectral scan and enable/disable it + * @spectral_scan_trigger: trigger a spectral scan run + * @spectral_scan_wait: wait for a spectral scan run to finish +@@ -745,6 +746,7 @@ struct ath_hw_ops { + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); ++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len); + void (*spectral_scan_config)(struct ath_hw *ah, + struct ath_spec_scan *param); + void (*spectral_scan_trigger)(struct ath_hw *ah); +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1915,6 +1915,26 @@ void ar9003_hw_init_rate_txpower(struct + } + } + ++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST(ah), AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST(ah), AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah), AR_PHY_TEST_CTL_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9); ++ udelay(1); ++ } ++ } ++} ++ + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +@@ -1951,6 +1971,7 @@ void ar9003_hw_attach_phy_ops(struct ath + priv_ops->set_radar_params = ar9003_hw_set_radar_params; + priv_ops->fast_chan_change = ar9003_hw_fast_chan_change; + ++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; + ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; + ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; + ops->spectral_scan_config = ar9003_hw_spectral_scan_config; +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -825,7 +825,8 @@ static void ath9k_init_txpower_limits(st + if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); + +- ah->curchan = curchan; ++ if (curchan) ++ ah->curchan = curchan; + } + + static const struct ieee80211_iface_limit if_limits[] = { +@@ -1003,6 +1004,18 @@ static void ath9k_set_hw_capab(struct at + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + } + ++static void ath_get_initial_entropy(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[256]; ++ ++ /* reuse last channel initialized by the tx power test */ ++ ath9k_hw_reset(ah, ah->curchan, NULL, false); ++ ++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf)); ++ add_device_randomness(buf, sizeof(buf)); ++} ++ + int ath9k_init_device(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +@@ -1050,6 +1063,8 @@ int ath9k_init_device(u16 devid, struct + + wiphy_read_of_freq_limits(hw->wiphy); + ++ ath_get_initial_entropy(sc); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) +--- a/drivers/net/wireless/ath/ath9k/hw-ops.h ++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h +@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp + ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); + } + ++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah, ++ u8 *buf, size_t len) ++{ ++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len); ++} ++ + #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT + + static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -1340,9 +1340,30 @@ void ar5008_hw_init_rate_txpower(struct + } + } + ++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8); ++ udelay(1); ++ } ++ } ++} ++ + int ar5008_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); ++ struct ath_hw_ops *ops = ath9k_hw_ops(ah); + static const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, +@@ -1357,6 +1378,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ + if (ret) + return ret; + ++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy; ++ + priv_ops->rf_set_freq = ar5008_hw_set_channel; + priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; + +--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h +@@ -20,6 +20,12 @@ + #define PHY_AGC_CLR 0x10000000 + #define RFSILENT_BB 0x00002000 + ++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000 ++#define AR_PHY_TEST_BBB_OBS_SEL_S 19 ++ ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) ++ + #define AR_PHY_TURBO 0x9804 + #define AR_PHY_FC_TURBO_MODE 0x00000001 + #define AR_PHY_FC_TURBO_SHORT 0x00000002 +@@ -36,6 +42,9 @@ + + #define AR_PHY_TEST2 0x9808 + ++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00 ++#define AR_PHY_TEST2_RX_OBS_SEL_S 10 ++ + #define AR_PHY_TIMING2 0x9810 + #define AR_PHY_TIMING3 0x9814 + #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +@@ -393,6 +402,8 @@ + #define AR_PHY_RFBUS_GRANT 0x9C20 + #define AR_PHY_RFBUS_GRANT_EN 0x00000001 + ++#define AR_PHY_TST_ADC 0x9C24 ++ + #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 + #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + diff --git a/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch b/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch new file mode 100644 index 0000000..926fbac --- /dev/null +++ b/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch @@ -0,0 +1,79 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -247,6 +247,19 @@ void ath9k_hw_get_channel_centers(struct + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); + } + ++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah) ++{ ++ /* On AR9330 and AR9340 devices, some PHY registers must be ++ * tuned to gain better stability/performance. These registers ++ * might be changed while doing wlan reset so the registers must ++ * be reprogrammed after each reset. ++ */ ++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20)); ++ REG_RMW(ah, AR_PHY_USB_CTRL2, ++ (1 << 21) | (0xf << 22), ++ (1 << 21) | (0x3 << 22)); ++} ++ + /******************/ + /* Chip Revisions */ + /******************/ +@@ -1454,6 +1467,9 @@ static bool ath9k_hw_set_reset(struct at + udelay(50); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1553,6 +1569,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); + ath9k_hw_init_pll(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1859,8 +1878,14 @@ static int ath9k_hw_do_fastcc(struct ath + if (AR_SREV_9271(ah)) + ar9002_hw_load_ani_reg(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + fail: ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return -EINVAL; + } + +@@ -2105,6 +2130,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ath9k_hw_set_radar_params(ah); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + } + EXPORT_SYMBOL(ath9k_hw_reset); +--- a/drivers/net/wireless/ath/ath9k/phy.h ++++ b/drivers/net/wireless/ath/ath9k/phy.h +@@ -48,6 +48,9 @@ + #define AR_PHY_PLL_CONTROL 0x16180 + #define AR_PHY_PLL_MODE 0x16184 + ++#define AR_PHY_USB_CTRL1 0x16c84 ++#define AR_PHY_USB_CTRL2 0x16c88 ++ + enum ath9k_ant_div_comb_lna_conf { + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, + ATH_ANT_DIV_COMB_LNA2, diff --git a/patches/ath9k/545-ath9k_ani_ws_detect.patch b/patches/ath9k/545-ath9k_ani_ws_detect.patch new file mode 100644 index 0000000..6027741 --- /dev/null +++ b/patches/ath9k/545-ath9k_ani_ws_detect.patch @@ -0,0 +1,155 @@ +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -969,55 +969,6 @@ static bool ar5008_hw_ani_control_new(st + * on == 0 means more noise imm + */ + u32 on = param ? 1 : 0; +- /* +- * make register setting for default +- * (weak sig detect ON) come from INI file +- */ +- int m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- int m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- int m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- int m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- int m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- int m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- int m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- int m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- int m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- int m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -42,20 +42,6 @@ static const int cycpwrThr1_table[] = + /* level: 0 1 2 3 4 5 6 7 8 */ + { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ + +-/* +- * register values to turn OFDM weak signal detection OFF +- */ +-static const int m1ThreshLow_off = 127; +-static const int m2ThreshLow_off = 127; +-static const int m1Thresh_off = 127; +-static const int m2Thresh_off = 127; +-static const int m2CountThr_off = 31; +-static const int m2CountThrLow_off = 63; +-static const int m1ThreshLowExt_off = 127; +-static const int m2ThreshLowExt_off = 127; +-static const int m1ThreshExt_off = 127; +-static const int m2ThreshExt_off = 127; +- + static const u8 ofdm2pwr[] = { + ALL_TARGET_LEGACY_6_24, + ALL_TARGET_LEGACY_6_24, +@@ -1065,11 +1051,6 @@ static bool ar9003_hw_ani_control(struct + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + struct ar5416AniState *aniState = &ah->ani; +- int m1ThreshLow, m2ThreshLow; +- int m1Thresh, m2Thresh; +- int m2CountThr, m2CountThrLow; +- int m1ThreshLowExt, m2ThreshLowExt; +- int m1ThreshExt, m2ThreshExt; + s32 value, value2; + + switch (cmd & ah->ani_function) { +@@ -1083,61 +1064,6 @@ static bool ar9003_hw_ani_control(struct + */ + u32 on = param ? 1 : 0; + +- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) +- goto skip_ws_det; +- +- m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, +- m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, +- m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, +- m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, +- m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, +- m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, +- m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, +- m2ThreshExt); +-skip_ws_det: + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); diff --git a/patches/ath9k/547-ath9k_led_defstate_fix.patch b/patches/ath9k/547-ath9k_led_defstate_fix.patch new file mode 100644 index 0000000..d633c05 --- /dev/null +++ b/patches/ath9k/547-ath9k_led_defstate_fix.patch @@ -0,0 +1,29 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 20:48:49 +0100 +Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs + +Support default state for platform LEDs connected to ath9k device. +Now LEDs are correctly set on or off at ath9k module initialization. +Very useful if power LED is connected to wireless chip. + +Signed-off-by: Michal Cieslakiewicz +--- + gpio.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -73,8 +73,11 @@ static int ath_add_led(struct ath_softc + ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + +- /* LED off */ +- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ /* Set default LED state */ ++ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON) ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low); ++ else ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + + return 0; + } diff --git a/patches/ath9k/548-ath9k_enable_gpio_chip.patch b/patches/ath9k/548-ath9k_enable_gpio_chip.patch new file mode 100644 index 0000000..7b0dd85 --- /dev/null +++ b/patches/ath9k/548-ath9k_enable_gpio_chip.patch @@ -0,0 +1,210 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 21:01:31 +0100 +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO + +Enable access to GPIO chip and its pins for Atheros AR92xx +wireless devices. For now AR9285 and AR9287 are supported. + +Signed-off-by: Michal Cieslakiewicz +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -25,6 +25,8 @@ + #include + #include + #include ++#include ++#include + + #include "common.h" + #include "debug.h" +@@ -1047,6 +1049,10 @@ struct ath_softc { + #ifdef CPTCFG_MAC80211_LEDS + const char *led_default_trigger; + struct list_head leds; ++#ifdef CONFIG_GPIOLIB ++ struct gpio_chip *gpiochip; ++ struct gpio_desc *gpiodesc; ++#endif + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -16,12 +16,120 @@ + + #include "ath9k.h" + ++#ifdef CPTCFG_MAC80211_LEDS ++ ++#ifdef CONFIG_GPIOLIB ++ ++/***************/ ++/* GPIO Chip */ ++/***************/ ++ ++/* gpio_chip handler : set GPIO to input */ ++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath_softc *sc = gpiochip_get_data(chip); ++ ++ ath9k_hw_gpio_request_in(sc->sc_ah, offset, "ath9k-gpio"); ++ ++ return 0; ++} ++ ++/* gpio_chip handler : set GPIO to output */ ++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct ath_softc *sc = gpiochip_get_data(chip); ++ ++ ath9k_hw_gpio_request_out(sc->sc_ah, offset, "ath9k-gpio", ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_set_gpio(sc->sc_ah, offset, value); ++ ++ return 0; ++} ++ ++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */ ++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath_softc *sc = gpiochip_get_data(chip); ++ struct ath_hw *ah = sc->sc_ah; ++ ++ return !((REG_READ(ah, AR_GPIO_OE_OUT(ah)) >> (offset * 2)) & 3); ++} ++ ++/* gpio_chip handler : get GPIO pin value */ ++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath_softc *sc = gpiochip_get_data(chip); ++ ++ return ath9k_hw_gpio_get(sc->sc_ah, offset); ++} ++ ++/* gpio_chip handler : set GPIO pin to value */ ++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct ath_softc *sc = gpiochip_get_data(chip); ++ ++ ath9k_hw_set_gpio(sc->sc_ah, offset, value); ++} ++ ++/* register GPIO chip */ ++static void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++ struct gpio_chip *gc = sc->gpiochip; ++ struct ath_hw *ah = sc->sc_ah; ++ ++ gc = kzalloc(sizeof(struct gpio_chip), GFP_KERNEL); ++ if (!gc) ++ return; ++ ++ gc->label = kasprintf(GFP_KERNEL, "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); ++ gc->parent = sc->dev; ++ gc->base = -1; /* determine base automatically */ ++ gc->ngpio = ah->caps.num_gpio_pins; ++ gc->direction_input = ath9k_gpio_pin_cfg_input; ++ gc->direction_output = ath9k_gpio_pin_cfg_output; ++ gc->get_direction = ath9k_gpio_pin_get_dir; ++ gc->get = ath9k_gpio_pin_get; ++ gc->set = ath9k_gpio_pin_set; ++ ++ if (gpiochip_add_data(gc, sc)) { ++ kfree(gc->label); ++ kfree(gc); ++ return; ++ } ++} ++ ++/* remove GPIO chip */ ++static void ath9k_unregister_gpio_chip(struct ath_softc *sc) ++{ ++ struct gpio_chip *gc = sc->gpiochip; ++ ++ if (!gc) ++ return; ++ ++ gpiochip_remove(gc); ++ kfree(gc->label); ++ kfree(gc); ++} ++ ++#else /* CONFIG_GPIOLIB */ ++ ++static inline void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++} ++ ++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc) ++{ ++} ++ ++#endif /* CONFIG_GPIOLIB */ ++ + /********************************/ + /* LED functions */ + /********************************/ + +-#ifdef CPTCFG_MAC80211_LEDS +- + static void ath_fill_led_pin(struct ath_softc *sc) + { + struct ath_hw *ah = sc->sc_ah; +@@ -79,6 +187,12 @@ static int ath_add_led(struct ath_softc + else + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + ++#ifdef CONFIG_GPIOLIB ++ /* If there is GPIO chip configured, reserve LED pin */ ++ if (sc->gpiochip) ++ sc->gpiodesc = gpiod_get(sc->dev, gpio->name, GPIOD_ASIS); ++#endif ++ + return 0; + } + +@@ -117,16 +231,23 @@ void ath_deinit_leds(struct ath_softc *s + + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); ++#ifdef CONFIG_GPIOLIB ++ /* If there is GPIO chip configured, free LED pin */ ++ if (sc->gpiochip) ++ gpiod_put(sc->gpiodesc); ++#endif + list_del(&led->list); + ath_led_brightness(&led->cdev, LED_OFF); + led_classdev_unregister(&led->cdev); + ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); + kfree(led); + } ++ ath9k_unregister_gpio_chip(sc); + } + + void ath_init_leds(struct ath_softc *sc) + { ++ struct device_node *np = sc->dev->of_node; + char led_name[32]; + const char *trigger; + +@@ -135,6 +256,15 @@ void ath_init_leds(struct ath_softc *sc) + if (AR_SREV_9100(sc->sc_ah)) + return; + ++ if (!np) ++ ath9k_register_gpio_chip(sc); ++ ++ /* setup gpio controller only if requested and skip the led_pin setup */ ++ if (of_property_read_bool(np, "gpio-controller")) { ++ ath9k_register_gpio_chip(sc); ++ return; ++ } ++ + ath_fill_led_pin(sc); + + snprintf(led_name, sizeof(led_name), "ath9k-%s", diff --git a/patches/ath9k/550-ath9k-of.patch b/patches/ath9k/550-ath9k-of.patch new file mode 100644 index 0000000..2db6177 --- /dev/null +++ b/patches/ath9k/550-ath9k-of.patch @@ -0,0 +1,166 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -28,6 +28,11 @@ + + #include "ath9k.h" + ++#ifdef CONFIG_ATH79 ++#include ++#include ++#endif ++ + struct ath9k_eeprom_ctx { + struct completion complete; + struct ath_hw *ah; +@@ -242,6 +247,81 @@ static unsigned int ath9k_reg_rmw(void * + return val; + } + ++#ifdef CONFIG_ATH79 ++#define QCA955X_DDR_CTL_CONFIG 0x108 ++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) ++ ++static int ar913x_wmac_reset(void) ++{ ++ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ ++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar933x_wmac_reset(void) ++{ ++ int retries = 20; ++ ++ ath79_device_reset_set(AR933X_RESET_WMAC); ++ ath79_device_reset_clear(AR933X_RESET_WMAC); ++ ++ while (1) { ++ u32 bootstrap; ++ ++ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0) ++ return 0; ++ ++ if (retries-- == 0) ++ break; ++ ++ udelay(10000); ++ } ++ ++ pr_err("ar933x: WMAC reset timed out"); ++ return -ETIMEDOUT; ++} ++ ++static int qca955x_wmac_reset(void) ++{ ++ int i; ++ ++ /* Try to wait for WMAC DDR activity to stop */ ++ for (i = 0; i < 10; i++) { ++ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) & ++ QCA955X_DDR_CTL_CONFIG_ACT_WMAC)) ++ break; ++ ++ udelay(10); ++ } ++ ++ ath79_device_reset_set(QCA955X_RESET_RTC); ++ udelay(10); ++ ath79_device_reset_clear(QCA955X_RESET_RTC); ++ udelay(10); ++ ++ return 0; ++} ++ ++ ++static int ar9330_get_soc_revision(void) ++{ ++ if (ath79_soc_rev == 1) ++ return ath79_soc_rev; ++ ++ return 0; ++} ++ ++static int ath79_get_soc_revision(void) ++{ ++ return ath79_soc_rev; ++} ++#endif ++ + /**************************/ + /* Initialization */ + /**************************/ +@@ -626,6 +706,7 @@ static int ath9k_of_init(struct ath_soft + struct ath_common *common = ath9k_hw_common(ah); + enum ath_bus_type bus_type = common->bus_ops->ath_bus_type; + char eeprom_name[100]; ++ u32 mask; + int ret; + + if (!of_device_is_available(np)) +@@ -633,6 +714,43 @@ static int ath9k_of_init(struct ath_soft + + ath_dbg(common, CONFIG, "parsing configuration from OF node\n"); + ++ if (!of_property_read_u32(np, "qca,gpio-mask", &mask)) ++ ah->caps.gpio_mask = mask; ++ ++ if (of_property_read_bool(np, "qca,tx-gain-buffalo")) ++ ah->config.tx_gain_buffalo = true; ++ ++#ifdef CONFIG_ATH79 ++ if (ah->hw_version.devid == AR5416_AR9100_DEVID) { ++ ah->external_reset = ar913x_wmac_reset; ++ } else if (ah->hw_version.devid == AR9300_DEVID_AR9330) { ++ ah->get_mac_revision = ar9330_get_soc_revision; ++ u32 t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ ah->is_clk_25mhz = !(t & AR933X_BOOTSTRAP_REF_CLK_40); ++ ah->external_reset = ar933x_wmac_reset; ++ } else if (ah->hw_version.devid == AR9300_DEVID_AR9340) { ++ ah->get_mac_revision = ath79_get_soc_revision; ++ u32 t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); ++ ah->is_clk_25mhz = !(t & AR934X_BOOTSTRAP_REF_CLK_40); ++ } else if (ah->hw_version.devid == AR9300_DEVID_AR953X) { ++ ah->get_mac_revision = ath79_get_soc_revision; ++ /* ++ * QCA953x only supports 25MHz refclk. ++ * Some vendors have an invalid bootstrap option ++ * set, which would break the WMAC here. ++ */ ++ ah->is_clk_25mhz = true; ++ } else if (ah->hw_version.devid == AR9300_DEVID_QCA955X) { ++ u32 t = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); ++ ah->is_clk_25mhz = !(t & QCA955X_BOOTSTRAP_REF_CLK_40); ++ ah->external_reset = qca955x_wmac_reset; ++ } else if (ah->hw_version.devid == AR9300_DEVID_QCA956X) { ++ ah->get_mac_revision = ath79_get_soc_revision; ++ u32 t = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP); ++ ah->is_clk_25mhz = !(t & QCA956X_BOOTSTRAP_REF_CLK_40); ++ } ++#endif ++ + if (of_property_read_bool(np, "qca,no-eeprom")) { + /* ath9k-eeprom--.bin */ + scnprintf(eeprom_name, sizeof(eeprom_name), +@@ -651,6 +769,17 @@ static int ath9k_of_init(struct ath_soft + if (ret == -EPROBE_DEFER) + return ret; + ++ np = of_get_child_by_name(np, "led"); ++ if (np && of_device_is_available(np)) { ++ u32 led_pin; ++ ++ if (!of_property_read_u32(np, "led-sources", &led_pin)) ++ ah->led_pin = led_pin; ++ ++ ah->config.led_active_high = !of_property_read_bool(np, "led-active-low"); ++ of_node_put(np); ++ } ++ + return 0; + } + diff --git a/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch b/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch new file mode 100644 index 0000000..7f826b8 --- /dev/null +++ b/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch @@ -0,0 +1,406 @@ +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -15,6 +15,7 @@ + */ + + #include "ath9k.h" ++#include "hsr.h" + + /* Set/change channels. If the channel is really being changed, it's done + * by resetting the chip. To accomplish this we must first cleanup any pending +@@ -22,6 +23,7 @@ + */ + static int ath_set_channel(struct ath_softc *sc) + { ++ struct device_node *np = sc->dev->of_node; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_hw *hw = sc->hw; +@@ -42,6 +44,11 @@ static int ath_set_channel(struct ath_so + ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", + chan->center_freq, chandef->width); + ++ if (of_property_read_bool(np, "ubnt,hsr")) { ++ ath9k_hsr_enable(ah, chandef->width, chan->center_freq); ++ ath9k_hsr_status(ah); ++ } ++ + /* update survey stats for the old channel before switching */ + spin_lock_irqsave(&common->cc_lock, flags); + ath_update_survey_stats(sc); +--- /dev/null ++++ b/drivers/net/wireless/ath/ath9k/hsr.c +@@ -0,0 +1,248 @@ ++/* ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Kirill Berezin ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hw.h" ++#include "ath9k.h" ++#include "hsr.h" ++ ++#define HSR_GPIO_CSN 8 ++#define HSR_GPIO_CLK 6 ++#define HSR_GPIO_DOUT 7 ++#define HSR_GPIO_DIN 5 ++ ++/* delays are in useconds */ ++#define HSR_DELAY_HALF_TICK 100 ++#define HSR_DELAY_PRE_WRITE 75 ++#define HSR_DELAY_FINAL 20000 ++#define HSR_DELAY_TRAILING 200 ++ ++void ath9k_hsr_init(struct ath_hw *ah) ++{ ++ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0); ++ ++ udelay(HSR_DELAY_TRAILING); ++} ++ ++static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ int i; ++ u32 rval = 0; ++ ++ udelay(delay); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ for (i = 0; i < 8; ++i) { ++ rval = rval << 1; ++ ++ /* pattern is left to right, that is 7-th bit runs first */ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ } ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n", ++ value, rval, rval > 32 ? rval : '-'); ++ ++ return rval & 0xff; ++} ++ ++static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items) ++{ ++ int status = 0; ++ int i = 0; ++ int err; ++ ++ /* a preamble */ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ ++ /* clear HSR's reply buffer */ ++ if (status) { ++ int loop = 0; ++ ++ for (loop = 0; (loop < 42) && status; ++loop) ++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, ++ 0); ++ ++ if (loop >= 42) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n"); ++ return -1; ++ } ++ } ++ ++ for (i = 0; (i < items) && (chain[i] != 0); ++i) ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]); ++ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ mdelay(HSR_DELAY_FINAL / 1000); ++ ++ /* reply */ ++ memset(chain, 0, items); ++ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ udelay(HSR_DELAY_TRAILING); ++ ++ for (i = 0; i < (items - 1); ++i) { ++ u32 ret; ++ ++ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ if (ret != 0) ++ chain[i] = (char)ret; ++ else ++ break; ++ ++ udelay(HSR_DELAY_TRAILING); ++ } ++ ++ if (i <= 1) ++ return 0; ++ ++ err = kstrtoint(chain + 1, 10, &i); ++ if (err) ++ return err; ++ ++ return i; ++} ++ ++int ath9k_hsr_disable(struct ath_hw *ah) ++{ ++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0}; ++ int ret; ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((ret > 0) && (*cmd == 'B')) ++ return 0; ++ ++ return -1; ++} ++ ++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) ++{ ++ char cmd[10]; ++ int ret; ++ ++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn ++ * 20MHz on invalid values ++ */ ++ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40)) ++ bw = 20; ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'b'; ++ snprintf(cmd + 1, 3, "%02d", bw); ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((*cmd != 'B') || (ret != bw)) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n", ++ 'b', bw, *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'x'; ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'X') { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'm'; ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'M') { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'f'; ++ snprintf(cmd + 1, 6, "%05d", fq); ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((*cmd != 'F') && (ret != fq)) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ath9k_hsr_status(struct ath_hw *ah) ++{ ++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++ int ret; ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'S') { ++ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd, ++ ret); ++ return -1; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath9k/hsr.h +@@ -0,0 +1,50 @@ ++/* ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Kirill Berezin ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#ifndef HSR_H ++#define HSR_H ++ ++ struct ath_hw; ++ ++#ifdef CPTCFG_ATH9K_UBNTHSR ++ ++void ath9k_hsr_init(struct ath_hw *ah); ++int ath9k_hsr_disable(struct ath_hw *ah); ++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq); ++int ath9k_hsr_status(struct ath_hw *ah); ++ ++#else ++static inline void ath9k_hsr_init(struct ath_hw *ah) {} ++ ++static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) ++{ ++ return 0; ++} ++ ++static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; } ++static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; } ++ ++#endif ++ ++#endif /* HSR_H */ +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -18,6 +18,7 @@ + #include + #include "ath9k.h" + #include "btcoex.h" ++#include "hsr.h" + + static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); +@@ -658,6 +659,7 @@ void ath_reset_work(struct work_struct * + static int ath9k_start(struct ieee80211_hw *hw) + { + struct ath_softc *sc = hw->priv; ++ struct device_node *np = sc->dev->of_node; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; +@@ -736,6 +738,11 @@ static int ath9k_start(struct ieee80211_ + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + } + ++ if (of_property_read_bool(np, "ubnt,hsr")) { ++ ath9k_hsr_init(ah); ++ ath9k_hsr_disable(ah); ++ } ++ + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. +--- a/drivers/net/wireless/ath/ath9k/Makefile ++++ b/drivers/net/wireless/ath/ath9k/Makefile +@@ -17,6 +17,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d + ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o + ath9k-$(CPTCFG_ATH9K_WOW) += wow.o + ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o ++ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o + + ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o + +--- a/local-symbols ++++ b/local-symbols +@@ -117,6 +117,7 @@ ATH9K_WOW= + ATH9K_RFKILL= + ATH9K_CHANNEL_CONTEXT= + ATH9K_PCOEM= ++ATH9K_UBNTHSR= + ATH9K_PCI_NO_EEPROM= + ATH9K_HTC= + ATH9K_HTC_DEBUGFS= +--- a/drivers/net/wireless/ath/ath9k/Kconfig ++++ b/drivers/net/wireless/ath/ath9k/Kconfig +@@ -58,6 +58,19 @@ config ATH9K_AHB + Say Y, if you have a SoC with a compatible built-in + wireless MAC. Say N if unsure. + ++config ATH9K_UBNTHSR ++ bool "Ubiquiti UniFi Outdoor Plus HSR support" ++ depends on ATH9K ++ ---help--- ++ This options enables code to control the HSR RF ++ filter in the receive path of the Ubiquiti UniFi ++ Outdoor Plus access point. ++ ++ Say Y if you want to use the access point. The ++ code will only be used if the device is detected, ++ so it does not harm other setup other than occupying ++ a bit of memory. ++ + config ATH9K_DEBUGFS + bool "Atheros ath9k debugging" + depends on ATH9K && DEBUG_FS && MAC80211_DEBUGFS diff --git a/patches/ath9k/552-ath9k-ahb_of.patch b/patches/ath9k/552-ath9k-ahb_of.patch new file mode 100644 index 0000000..04c821a --- /dev/null +++ b/patches/ath9k/552-ath9k-ahb_of.patch @@ -0,0 +1,100 @@ +--- a/drivers/net/wireless/ath/ath9k/ahb.c ++++ b/drivers/net/wireless/ath/ath9k/ahb.c +@@ -16,37 +16,21 @@ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#include ++#include + #include ++#include + #include +-#include +-#include ++ + #include "ath9k.h" + +-static const struct platform_device_id ath9k_platform_id_table[] = { +- { +- .name = "ath9k", +- .driver_data = AR5416_AR9100_DEVID, +- }, +- { +- .name = "ar933x_wmac", +- .driver_data = AR9300_DEVID_AR9330, +- }, +- { +- .name = "ar934x_wmac", +- .driver_data = AR9300_DEVID_AR9340, +- }, +- { +- .name = "qca955x_wmac", +- .driver_data = AR9300_DEVID_QCA955X, +- }, +- { +- .name = "qca953x_wmac", +- .driver_data = AR9300_DEVID_AR953X, +- }, +- { +- .name = "qca956x_wmac", +- .driver_data = AR9300_DEVID_QCA956X, +- }, ++static const struct of_device_id ath9k_of_match_table[] = { ++ { .compatible = "qca,ar9130-wifi", .data = (void *)AR5416_AR9100_DEVID }, ++ { .compatible = "qca,ar9330-wifi", .data = (void *)AR9300_DEVID_AR9330 }, ++ { .compatible = "qca,ar9340-wifi", .data = (void *)AR9300_DEVID_AR9340 }, ++ { .compatible = "qca,qca9530-wifi", .data = (void *)AR9300_DEVID_AR953X }, ++ { .compatible = "qca,qca9550-wifi", .data = (void *)AR9300_DEVID_QCA955X }, ++ { .compatible = "qca,qca9560-wifi", .data = (void *)AR9300_DEVID_QCA956X }, + {}, + }; + +@@ -71,19 +55,14 @@ static const struct ath_bus_ops ath_ahb_ + + static int ath_ahb_probe(struct platform_device *pdev) + { +- void __iomem *mem; +- struct ath_softc *sc; + struct ieee80211_hw *hw; +- const struct platform_device_id *id = platform_get_device_id(pdev); +- int irq; +- int ret = 0; ++ struct ath_softc *sc; + struct ath_hw *ah; ++ void __iomem *mem; + char hw_name[64]; +- +- if (!dev_get_platdata(&pdev->dev)) { +- dev_err(&pdev->dev, "no platform data specified\n"); +- return -EINVAL; +- } ++ u16 dev_id; ++ int irq; ++ int ret; + + mem = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mem)) { +@@ -117,7 +96,8 @@ static int ath_ahb_probe(struct platform + goto err_free_hw; + } + +- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops); ++ dev_id = (u16)(kernel_ulong_t)of_device_get_match_data(&pdev->dev); ++ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops); + if (ret) { + dev_err(&pdev->dev, "failed to initialize device\n"); + goto err_irq; +@@ -167,11 +147,11 @@ static struct platform_driver ath_ahb_dr + + .driver = { + .name = "ath9k", ++ .of_match_table = ath9k_of_match_table, + }, +- .id_table = ath9k_platform_id_table, + }; + +-MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table); ++MODULE_DEVICE_TABLE(of, ath9k_of_match_table); + + int ath_ahb_init(void) + { diff --git a/patches/brcm/040-brcmutil_option.patch b/patches/brcm/040-brcmutil_option.patch new file mode 100644 index 0000000..3e8505b --- /dev/null +++ b/patches/brcm/040-brcmutil_option.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig ++++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config BRCMUTIL +- tristate ++ tristate "Broadcom 802.11 driver utility functions" + depends on m + + config BRCMSMAC diff --git a/patches/brcm/810-b43-gpio-mask-module-option.patch b/patches/brcm/810-b43-gpio-mask-module-option.patch new file mode 100644 index 0000000..295a4cc --- /dev/null +++ b/patches/brcm/810-b43-gpio-mask-module-option.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/broadcom/b43/b43.h ++++ b/drivers/net/wireless/broadcom/b43/b43.h +@@ -840,6 +840,7 @@ struct b43_wldev { + bool qos_enabled; /* TRUE, if QoS is used. */ + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ ++ int gpiomask; /* GPIO LED mask as a module parameter */ + + /* PHY/Radio device. */ + struct b43_phy phy; +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -72,6 +72,11 @@ MODULE_FIRMWARE("b43/ucode40.fw"); + MODULE_FIRMWARE("b43/ucode42.fw"); + MODULE_FIRMWARE("b43/ucode9.fw"); + ++static int modparam_gpiomask = 0x000F; ++module_param_named(gpiomask, modparam_gpiomask, int, 0444); ++MODULE_PARM_DESC(gpiomask, ++ "GPIO mask for LED control (default 0x000F)"); ++ + static int modparam_bad_frames_preempt; + module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); + MODULE_PARM_DESC(bad_frames_preempt, +@@ -2870,10 +2875,10 @@ static int b43_gpio_init(struct b43_wlde + u32 mask, set; + + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); +- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF); ++ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask); + + mask = 0x0000001F; +- set = 0x0000000F; ++ set = modparam_gpiomask; + if (dev->dev->chip_id == 0x4301) { + mask |= 0x0060; + set |= 0x0060; diff --git a/patches/brcm/811-b43_no_pio.patch b/patches/brcm/811-b43_no_pio.patch new file mode 100644 index 0000000..e395d48 --- /dev/null +++ b/patches/brcm/811-b43_no_pio.patch @@ -0,0 +1,86 @@ +--- a/drivers/net/wireless/broadcom/b43/Makefile ++++ b/drivers/net/wireless/broadcom/b43/Makefile +@@ -18,7 +18,7 @@ b43-$(CPTCFG_B43_PHY_AC) += phy_ac.o + b43-y += sysfs.o + b43-y += xmit.o + b43-y += dma.o +-b43-y += pio.o ++b43-$(CPTCFG_B43_PIO) += pio.o + b43-y += rfkill.o + b43-y += ppr.o + b43-$(CPTCFG_B43_LEDS) += leds.o +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -2001,10 +2001,12 @@ static void b43_do_interrupt_thread(stru + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3], + dma_reason[4], dma_reason[5]); ++#ifdef CPTCFG_B43_PIO + b43err(dev->wl, "This device does not support DMA " + "on your system. It will now be switched to PIO.\n"); + /* Fall back to PIO transfers if we get fatal DMA errors! */ + dev->use_pio = true; ++#endif + b43_controller_restart(dev, "DMA error"); + return; + } +--- a/drivers/net/wireless/broadcom/b43/pio.h ++++ b/drivers/net/wireless/broadcom/b43/pio.h +@@ -151,7 +151,7 @@ static inline void b43_piorx_write32(str + b43_write32(q->dev, q->mmio_base + offset, value); + } + +- ++#ifdef CPTCFG_B43_PIO + int b43_pio_init(struct b43_wldev *dev); + void b43_pio_free(struct b43_wldev *dev); + +@@ -162,5 +162,37 @@ void b43_pio_rx(struct b43_pio_rxqueue * + + void b43_pio_tx_suspend(struct b43_wldev *dev); + void b43_pio_tx_resume(struct b43_wldev *dev); ++#else ++static inline int b43_pio_init(struct b43_wldev *dev) ++{ ++ return 0; ++} ++ ++static inline void b43_pio_free(struct b43_wldev *dev) ++{ ++} ++ ++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) ++{ ++ return 0; ++} ++ ++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, ++ const struct b43_txstatus *status) ++{ ++} ++ ++static inline void b43_pio_rx(struct b43_pio_rxqueue *q) ++{ ++} ++ ++static inline void b43_pio_tx_suspend(struct b43_wldev *dev) ++{ ++} ++ ++static inline void b43_pio_tx_resume(struct b43_wldev *dev) ++{ ++} ++#endif /* CPTCFG_B43_PIO */ + + #endif /* B43_PIO_H_ */ +--- a/drivers/net/wireless/broadcom/b43/Kconfig ++++ b/drivers/net/wireless/broadcom/b43/Kconfig +@@ -100,7 +100,7 @@ config B43_BCMA_PIO + default y + + config B43_PIO +- bool ++ bool "Broadcom 43xx PIO support" + depends on B43 && B43_SSB + depends on SSB_BLOCKIO + default y diff --git a/patches/brcm/812-b43-add-antenna-control.patch b/patches/brcm/812-b43-add-antenna-control.patch new file mode 100644 index 0000000..e9f915d --- /dev/null +++ b/patches/brcm/812-b43-add-antenna-control.patch @@ -0,0 +1,131 @@ +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -1643,7 +1643,7 @@ static void b43_write_beacon_template(st + len, ram_offset, shm_size_offset, rate); + + /* Write the PHY TX control parameters. */ +- antenna = B43_ANTENNA_DEFAULT; ++ antenna = dev->tx_antenna; + antenna = b43_antenna_to_phyctl(antenna); + ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); + /* We can't send beacons with short preamble. Would get PHY errors. */ +@@ -3285,8 +3285,8 @@ static int b43_chip_init(struct b43_wlde + + /* Select the antennae */ + if (phy->ops->set_rx_antenna) +- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); +- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); ++ phy->ops->set_rx_antenna(dev, dev->rx_antenna); ++ b43_mgmtframe_txantenna(dev, dev->tx_antenna); + + if (phy->type == B43_PHYTYPE_B) { + value16 = b43_read16(dev, 0x005E); +@@ -3988,7 +3988,6 @@ static int b43_op_config(struct ieee8021 + struct b43_wldev *dev = wl->current_dev; + struct b43_phy *phy = &dev->phy; + struct ieee80211_conf *conf = &hw->conf; +- int antenna; + int err = 0; + + mutex_lock(&wl->mutex); +@@ -4031,11 +4030,9 @@ static int b43_op_config(struct ieee8021 + } + + /* Antennas for RX and management frame TX. */ +- antenna = B43_ANTENNA_DEFAULT; +- b43_mgmtframe_txantenna(dev, antenna); +- antenna = B43_ANTENNA_DEFAULT; ++ b43_mgmtframe_txantenna(dev, dev->tx_antenna); + if (phy->ops->set_rx_antenna) +- phy->ops->set_rx_antenna(dev, antenna); ++ phy->ops->set_rx_antenna(dev, dev->rx_antenna); + + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { +@@ -5178,6 +5175,47 @@ static int b43_op_get_survey(struct ieee + return 0; + } + ++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) ++{ ++ struct b43_wl *wl = hw_to_b43_wl(hw); ++ struct b43_wldev *dev = wl->current_dev; ++ ++ if (tx_ant == 1 && rx_ant == 1) { ++ dev->tx_antenna = B43_ANTENNA0; ++ dev->rx_antenna = B43_ANTENNA0; ++ } ++ else if (tx_ant == 2 && rx_ant == 2) { ++ dev->tx_antenna = B43_ANTENNA1; ++ dev->rx_antenna = B43_ANTENNA1; ++ } ++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) { ++ dev->tx_antenna = B43_ANTENNA_DEFAULT; ++ dev->rx_antenna = B43_ANTENNA_DEFAULT; ++ } ++ else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++ ++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) ++{ ++ struct b43_wl *wl = hw_to_b43_wl(hw); ++ struct b43_wldev *dev = wl->current_dev; ++ ++ switch (dev->tx_antenna) { ++ case B43_ANTENNA0: ++ *tx_ant = 1; *rx_ant = 1; break; ++ case B43_ANTENNA1: ++ *tx_ant = 2; *rx_ant = 2; break; ++ case B43_ANTENNA_DEFAULT: ++ *tx_ant = 3; *rx_ant = 3; break; ++ } ++ return 0; ++} ++ + static const struct ieee80211_ops b43_hw_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, +@@ -5204,6 +5242,8 @@ static const struct ieee80211_ops b43_hw + .sw_scan_complete = b43_op_sw_scan_complete_notifier, + .get_survey = b43_op_get_survey, + .rfkill_poll = b43_rfkill_poll, ++ .set_antenna = b43_op_set_antenna, ++ .get_antenna = b43_op_get_antenna, + }; + + /* Hard-reset the chip. Do not call this directly. +@@ -5505,6 +5545,8 @@ static int b43_one_core_attach(struct b4 + if (!wldev) + goto out; + ++ wldev->rx_antenna = B43_ANTENNA_DEFAULT; ++ wldev->tx_antenna = B43_ANTENNA_DEFAULT; + wldev->use_pio = b43_modparam_pio; + wldev->dev = dev; + wldev->wl = wl; +@@ -5596,6 +5638,9 @@ static struct b43_wl *b43_wireless_init( + + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + ++ hw->wiphy->available_antennas_rx = 0x3; ++ hw->wiphy->available_antennas_tx = 0x3; ++ + wl->hw_registered = false; + hw->max_rates = 2; + SET_IEEE80211_DEV(hw, dev->dev); +--- a/drivers/net/wireless/broadcom/b43/b43.h ++++ b/drivers/net/wireless/broadcom/b43/b43.h +@@ -841,6 +841,8 @@ struct b43_wldev { + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ + int gpiomask; /* GPIO LED mask as a module parameter */ ++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */ ++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */ + + /* PHY/Radio device. */ + struct b43_phy phy; diff --git a/patches/brcm/813-b43-reduce-number-of-RX-slots.patch b/patches/brcm/813-b43-reduce-number-of-RX-slots.patch new file mode 100644 index 0000000..85c52c0 --- /dev/null +++ b/patches/brcm/813-b43-reduce-number-of-RX-slots.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/broadcom/b43/dma.h ++++ b/drivers/net/wireless/broadcom/b43/dma.h +@@ -170,7 +170,7 @@ struct b43_dmadesc_generic { + + /* DMA engine tuning knobs */ + #define B43_TXRING_SLOTS 256 +-#define B43_RXRING_SLOTS 256 ++#define B43_RXRING_SLOTS 32 + #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) + #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) + diff --git a/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch b/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch new file mode 100644 index 0000000..f7aa413 --- /dev/null +++ b/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch @@ -0,0 +1,17 @@ +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -2887,6 +2887,14 @@ static int b43_gpio_init(struct b43_wlde + } else if (dev->dev->chip_id == 0x5354) { + /* Don't allow overtaking buttons GPIOs */ + set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */ ++ } else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) { ++ /* just use gpio 0 and 1 for 2.4 GHz wifi led */ ++ set &= 0x3; ++ mask &= 0x3; + } + + if (0 /* FIXME: conditional unknown */ ) { diff --git a/patches/brcm/815-b43-always-take-overlapping-devs.patch b/patches/brcm/815-b43-always-take-overlapping-devs.patch new file mode 100644 index 0000000..3700eaa --- /dev/null +++ b/patches/brcm/815-b43-always-take-overlapping-devs.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -114,7 +114,7 @@ static int b43_modparam_pio; + module_param_named(pio, b43_modparam_pio, int, 0644); + MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); + +-static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC); ++static int modparam_allhwsupport = 1; + module_param_named(allhwsupport, modparam_allhwsupport, int, 0444); + MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)"); + diff --git a/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch b/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch new file mode 100644 index 0000000..3c93386 --- /dev/null +++ b/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch @@ -0,0 +1,27 @@ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c +@@ -58,19 +58,12 @@ + (((c) < 149) ? 3 : 4)))) + + #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) +-#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ +- NL80211_RRF_NO_IR) ++#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, 0) + +-#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ +- NL80211_RRF_DFS | \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ +- NL80211_RRF_DFS | \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ +- NL80211_RRF_NO_IR) ++#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, 0) + + static const struct ieee80211_regdomain brcms_regdom_x2 = { + .n_reg_rules = 6, diff --git a/patches/brcm/860-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/patches/brcm/860-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch new file mode 100644 index 0000000..9992ccf --- /dev/null +++ b/patches/brcm/860-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -0,0 +1,49 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 9 Jul 2015 00:07:59 +0200 +Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -983,8 +983,36 @@ static struct wireless_dev *brcmf_cfg802 + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; + struct wireless_dev *wdev; ++ struct net_device *dev; + int err; + ++ /* ++ * There is a bug with in-firmware BSS management. When adding virtual ++ * interface brcmfmac first tells firmware to create new BSS and then ++ * it creates new struct net_device. ++ * ++ * If creating/registering netdev(ice) fails, BSS remains in some bugged ++ * state. It conflicts with existing BSSes by overtaking their auth ++ * requests. ++ * ++ * It results in one BSS (addresss X) sending beacons and another BSS ++ * (address Y) replying to authentication requests. This makes interface ++ * unusable as AP. ++ * ++ * To workaround this bug we may try to guess if register_netdev(ice) ++ * will fail. The most obvious case is using interface name that already ++ * exists. This is actually quite likely with brcmfmac & some user space ++ * scripts as brcmfmac doesn't allow deleting virtual interfaces. ++ * So this bug can be triggered even by something trivial like: ++ * iw dev wlan0 delete ++ * iw phy phy0 interface add wlan0 type __ap ++ */ ++ dev = dev_get_by_name(&init_net, name); ++ if (dev) { ++ dev_put(dev); ++ return ERR_PTR(-ENFILE); ++ } ++ + brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); + err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); + if (err) { diff --git a/patches/brcm/861-brcmfmac-add-in-driver-tables-with-country-codes.patch b/patches/brcm/861-brcmfmac-add-in-driver-tables-with-country-codes.patch new file mode 100644 index 0000000..2f07212 --- /dev/null +++ b/patches/brcm/861-brcmfmac-add-in-driver-tables-with-country-codes.patch @@ -0,0 +1,60 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] brcmfmac: add in-driver tables with country codes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds early support for changing region. Ideally this data should +be stored in DT as all these mappings are devices specific. + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -66,6 +66,36 @@ static int brcmf_of_get_country_codes(st + return 0; + } + ++/* TODO: FIXME: Use DT */ ++static void brcmf_of_probe_cc(struct device *dev, ++ struct brcmf_mp_device *settings) ++{ ++ static struct brcmfmac_pd_cc_entry netgear_r8000_cc_ent[] = { ++ { "JP", "JP", 78 }, ++ { "US", "Q2", 86 }, ++ }; ++ struct brcmfmac_pd_cc_entry *cc_ent = NULL; ++ int table_size = 0; ++ ++ if (of_machine_is_compatible("netgear,r8000")) { ++ cc_ent = netgear_r8000_cc_ent; ++ table_size = ARRAY_SIZE(netgear_r8000_cc_ent); ++ } ++ ++ if (cc_ent && table_size) { ++ struct brcmfmac_pd_cc *cc; ++ size_t memsize; ++ ++ memsize = table_size * sizeof(struct brcmfmac_pd_cc_entry); ++ cc = devm_kzalloc(dev, sizeof(*cc) + memsize, GFP_KERNEL); ++ if (!cc) ++ return; ++ cc->table_size = table_size; ++ memcpy(cc->table, cc_ent, memsize); ++ settings->country_codes = cc; ++ } ++} ++ + int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) + { +@@ -121,6 +151,8 @@ int brcmf_of_probe(struct device *dev, e + + brcmf_dbg(INFO, "%s LPO clock\n", clk ? "enable" : "no"); + ++ brcmf_of_probe_cc(dev, settings); ++ + if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) + return 0; + diff --git a/patches/brcm/870-01-rpi-6.12-brcmfmac-adds-support-for-BCM43341-wifi.patch b/patches/brcm/870-01-rpi-6.12-brcmfmac-adds-support-for-BCM43341-wifi.patch new file mode 100644 index 0000000..23526c9 --- /dev/null +++ b/patches/brcm/870-01-rpi-6.12-brcmfmac-adds-support-for-BCM43341-wifi.patch @@ -0,0 +1,29 @@ +From 88759af56f126e6e151f07fa9efc7447079fca9d Mon Sep 17 00:00:00 2001 +From: Cheong2K +Date: Fri, 26 Feb 2016 18:20:10 +0800 +Subject: [PATCH] brcmfmac: adds support for BCM43341 wifi + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 ++- + 3 files changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -609,6 +609,7 @@ BRCMF_FW_DEF(4329, "brcmfmac4329-sdio"); + BRCMF_FW_DEF(4330, "brcmfmac4330-sdio"); + BRCMF_FW_DEF(4334, "brcmfmac4334-sdio"); + BRCMF_FW_DEF(43340, "brcmfmac43340-sdio"); ++BRCMF_FW_DEF(43341, "brcmfmac43341-sdio"); + BRCMF_FW_DEF(4335, "brcmfmac4335-sdio"); + BRCMF_FW_DEF(43362, "brcmfmac43362-sdio"); + BRCMF_FW_DEF(4339, "brcmfmac4339-sdio"); +@@ -641,7 +642,7 @@ static const struct brcmf_firmware_mappi + BRCMF_FW_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), +- BRCMF_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340), ++ BRCMF_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), + BRCMF_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), diff --git a/patches/brcm/870-02-rpi-6.12-brcmfmac-Prefer-a-ccode-from-OTP-over-nvram-file.patch b/patches/brcm/870-02-rpi-6.12-brcmfmac-Prefer-a-ccode-from-OTP-over-nvram-file.patch new file mode 100644 index 0000000..9063bba --- /dev/null +++ b/patches/brcm/870-02-rpi-6.12-brcmfmac-Prefer-a-ccode-from-OTP-over-nvram-file.patch @@ -0,0 +1,130 @@ +From 3ac592da09acb47b728ef320e9fecde55c8e0824 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 26 Jun 2020 11:51:05 +0100 +Subject: [PATCH] brcmfmac: Prefer a ccode from OTP over nvram file + +Allow the nvram file to set a default ccode (regulatory domain) without +overriding one set in OTP. + +Signed-off-by: Phil Elwell +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 39 +++++++++++++------ + .../broadcom/brcm80211/brcmfmac/firmware.c | 21 +++++++++- + 2 files changed, 47 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -8223,31 +8224,45 @@ static void brcmf_cfg80211_reg_notifier( + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); + struct brcmf_pub *drvr = cfg->pub; + struct brcmf_fil_country_le ccreq; ++ char *alpha2; + s32 err; + int i; + +- /* The country code gets set to "00" by default at boot, ignore */ +- if (req->alpha2[0] == '0' && req->alpha2[1] == '0') ++ err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); ++ if (err) { ++ bphy_err(drvr, "Country code iovar returned err = %d\n", err); + return; ++ } ++ ++ /* The country code gets set to "00" by default at boot - substitute ++ * any saved ccode from the nvram file unless there is a valid code ++ * already set. ++ */ ++ alpha2 = req->alpha2; ++ if (alpha2[0] == '0' && alpha2[1] == '0') { ++ extern char saved_ccode[2]; ++ ++ if ((isupper(ccreq.country_abbrev[0]) && ++ isupper(ccreq.country_abbrev[1])) || ++ !saved_ccode[0]) ++ return; ++ alpha2 = saved_ccode; ++ pr_debug("brcmfmac: substituting saved ccode %c%c\n", ++ alpha2[0], alpha2[1]); ++ } + + /* ignore non-ISO3166 country codes */ + for (i = 0; i < 2; i++) +- if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { ++ if (alpha2[i] < 'A' || alpha2[i] > 'Z') { + bphy_err(drvr, "not an ISO3166 code (0x%02x 0x%02x)\n", +- req->alpha2[0], req->alpha2[1]); ++ alpha2[0], alpha2[1]); + return; + } + + brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator, +- req->alpha2[0], req->alpha2[1]); +- +- err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); +- if (err) { +- bphy_err(drvr, "Country code iovar returned err = %d\n", err); +- return; +- } ++ alpha2[0], alpha2[1]); + +- err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq); ++ err = brcmf_translate_country_code(ifp->drvr, alpha2, &ccreq); + if (err) + return; + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "firmware.h" +@@ -32,6 +33,8 @@ enum nvram_parser_state { + END + }; + ++char saved_ccode[2] = {}; ++ + /** + * struct nvram_parser - internal info for parser. + * +@@ -562,11 +565,27 @@ static int brcmf_fw_request_nvram_done(c + goto fail; + } + +- if (data) ++ if (data) { ++ char *ccode = strnstr((char *)data, "ccode=", data_len); ++ /* Ensure this is a whole token */ ++ if (ccode && ((void *)ccode == (void *)data || isspace(ccode[-1]))) { ++ /* Comment out the line */ ++ ccode[0] = '#'; ++ ccode += 6; ++ if (isupper(ccode[0]) && isupper(ccode[1]) && ++ isspace(ccode[2])) { ++ pr_debug("brcmfmac: intercepting ccode=%c%c\n", ++ ccode[0], ccode[1]); ++ saved_ccode[0] = ccode[0]; ++ saved_ccode[1] = ccode[1]; ++ } ++ }; ++ + nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length, + fwctx->req->domain_nr, + fwctx->req->bus_nr, + fwctx->dev); ++ } + + if (free_bcm47xx_nvram) + bcm47xx_nvram_release_contents(data); diff --git a/patches/brcm/870-03-rpi-6.12-brcmfmac-Increase-power-saving-delay-to-2s.patch b/patches/brcm/870-03-rpi-6.12-brcmfmac-Increase-power-saving-delay-to-2s.patch new file mode 100644 index 0000000..089c0ea --- /dev/null +++ b/patches/brcm/870-03-rpi-6.12-brcmfmac-Increase-power-saving-delay-to-2s.patch @@ -0,0 +1,24 @@ +From 12722e472a963598a88011dd4b6805ed0a0e318f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 3 Feb 2020 09:32:22 +0000 +Subject: [PATCH] brcmfmac: Increase power saving delay to 2s + +Increase the delay before entering the lower power state to 2 seconds +(the maximum allowed) in order to reduce the packet latencies, +particularly for inbound packets. + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -3343,6 +3343,7 @@ brcmf_cfg80211_set_power_mgmt(struct wip + bphy_err(drvr, "error (%d)\n", err); + } + ++ timeout = 2000; /* 2000ms - the maximum */ + err = brcmf_fil_iovar_int_set(ifp, "pm2_sleep_ret", + min_t(u32, timeout, BRCMF_PS_MAX_TIMEOUT_MS)); + if (err) diff --git a/patches/brcm/870-04-rpi-6.12-brcmfmac-non-upstream-support-DS1-exit-firmware-re-download.patch b/patches/brcm/870-04-rpi-6.12-brcmfmac-non-upstream-support-DS1-exit-firmware-re-download.patch new file mode 100644 index 0000000..74a373e --- /dev/null +++ b/patches/brcm/870-04-rpi-6.12-brcmfmac-non-upstream-support-DS1-exit-firmware-re-download.patch @@ -0,0 +1,721 @@ +From e7400640cafcf6bd84049308feb5aeabecf55b46 Mon Sep 17 00:00:00 2001 +From: Praveen Babu C +Date: Tue, 9 Jan 2018 11:33:10 +0530 +Subject: [PATCH] non-upstream: support DS1 exit firmware re-download + +In deep sleep mode (DS1) ARM is off and once exit trigger comes than +mailbox Interrupt comes to host and whole reinitiation should be done +in the ARM to start TX/RX. + +Also fix below issus for DS1 exit: +1. Sent Tx Control frame only after firmware redownload complete (check +F2 Ready before sending Tx Control frame to Firmware) +2. intermittent High DS1 TX Exit latency time (almost 3sec) ==> This is +fixed by skipping host Mailbox interrupt Multiple times (ulp state +mechanism) +3. RX GlOM save/restore in Firmware +4. Add ULP event enable & event_msgs_ext iovar configuration in FMAC +5. Add ULP_EVENT_RECV state machine for sbwad support +6. Support 2 Byte Shared memory read for DS1 Exit HUDI implementation + +Signed-off-by: Praveen Babu C +Signed-off-by: Naveen Gupta +[Merge from 4.14.77 to 5.4.18; set BRCMF_SDIO_MAX_ACCESS_ERRORS to 20] +Signed-off-by: Chi-hsien Lin +JIRA: SWWLAN-135583 +JIRA: SWWLAN-136577 +--- + .../broadcom/brcm80211/brcmfmac/bus.h | 2 +- + .../broadcom/brcm80211/brcmfmac/common.c | 39 +++ + .../broadcom/brcm80211/brcmfmac/core.c | 13 +- + .../broadcom/brcm80211/brcmfmac/debug.h | 1 + + .../broadcom/brcm80211/brcmfmac/fweh.h | 31 ++- + .../broadcom/brcm80211/brcmfmac/pcie.c | 2 +- + .../broadcom/brcm80211/brcmfmac/sdio.c | 260 +++++++++++++++++- + .../broadcom/brcm80211/brcmfmac/sdio.h | 110 ++++++++ + .../broadcom/brcm80211/brcmfmac/usb.c | 4 +- + .../broadcom/brcm80211/include/chipcommon.h | 2 + + 10 files changed, 448 insertions(+), 16 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -298,7 +298,7 @@ void brcmf_rx_event(struct device *dev, + + int brcmf_alloc(struct device *dev, struct brcmf_mp_device *settings); + /* Indication from bus module regarding presence/insertion of dongle. */ +-int brcmf_attach(struct device *dev); ++int brcmf_attach(struct device *dev, bool start_bus); + /* Indication from bus module regarding removal/absence of dongle */ + void brcmf_detach(struct device *dev); + void brcmf_free(struct device *dev); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -20,6 +20,8 @@ + #include "of.h" + #include "firmware.h" + #include "chip.h" ++#include "fweh.h" ++#include + + MODULE_AUTHOR("Broadcom Corporation"); + MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); +@@ -274,6 +276,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_i + char *clmver; + char *ptr; + s32 err; ++ struct eventmsgs_ext *eventmask_msg = NULL; ++ u8 msglen; + + if (is_valid_ether_addr(ifp->mac_addr)) { + /* set mac address */ +@@ -433,6 +437,41 @@ int brcmf_c_preinit_dcmds(struct brcmf_i + goto done; + } + ++ /* Enable event_msg_ext specific to 43012 chip */ ++ if (bus->chip == CY_CC_43012_CHIP_ID) { ++ /* Program event_msg_ext to support event larger than 128 */ ++ msglen = (roundup(BRCMF_E_LAST, NBBY) / NBBY) + ++ EVENTMSGS_EXT_STRUCT_SIZE; ++ /* Allocate buffer for eventmask_msg */ ++ eventmask_msg = kzalloc(msglen, GFP_KERNEL); ++ if (!eventmask_msg) { ++ err = -ENOMEM; ++ goto done; ++ } ++ ++ /* Read the current programmed event_msgs_ext */ ++ eventmask_msg->ver = EVENTMSGS_VER; ++ eventmask_msg->len = roundup(BRCMF_E_LAST, NBBY) / NBBY; ++ err = brcmf_fil_iovar_data_get(ifp, "event_msgs_ext", ++ eventmask_msg, ++ msglen); ++ ++ /* Enable ULP event */ ++ brcmf_dbg(EVENT, "enable event ULP\n"); ++ setbit(eventmask_msg->mask, BRCMF_E_ULP); ++ ++ /* Write updated Event mask */ ++ eventmask_msg->ver = EVENTMSGS_VER; ++ eventmask_msg->command = EVENTMSGS_SET_MASK; ++ eventmask_msg->len = (roundup(BRCMF_E_LAST, NBBY) / NBBY); ++ ++ err = brcmf_fil_iovar_data_set(ifp, "event_msgs_ext", ++ eventmask_msg, msglen); ++ if (err) { ++ brcmf_err("Set event_msgs_ext error (%d)\n", err); ++ goto done; ++ } ++ } + /* Setup default scan channel time */ + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, + BRCMF_DEFAULT_SCAN_CHANNEL_TIME); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -1322,7 +1322,7 @@ int brcmf_alloc(struct device *dev, stru + return 0; + } + +-int brcmf_attach(struct device *dev) ++int brcmf_attach(struct device *dev, bool start_bus) + { + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; +@@ -1365,10 +1365,13 @@ int brcmf_attach(struct device *dev) + + brcmf_fwvid_get_cfg80211_ops(drvr); + +- ret = brcmf_bus_started(drvr, drvr->ops); +- if (ret != 0) { +- bphy_err(drvr, "dongle is not responding: err=%d\n", ret); +- goto fail; ++ if (start_bus) { ++ ret = brcmf_bus_started(drvr, drvr->ops); ++ if (ret != 0) { ++ bphy_err(drvr, "dongle is not responding: err=%d\n", ++ ret); ++ goto fail; ++ } + } + + return 0; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +@@ -29,6 +29,7 @@ + #define BRCMF_MSGBUF_VAL 0x00040000 + #define BRCMF_PCIE_VAL 0x00080000 + #define BRCMF_FWCON_VAL 0x00100000 ++#define BRCMF_ULP_VAL 0x00200000 + + /* set default print format */ + #undef pr_fmt +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h +@@ -98,7 +98,8 @@ struct brcmf_cfg80211_info; + BRCMF_ABSTRACT_ENUM_DEF(EXT_AUTH_REQ, 0) \ + BRCMF_ABSTRACT_ENUM_DEF(EXT_AUTH_FRAME_RX, 1) \ + BRCMF_ABSTRACT_ENUM_DEF(MGMT_FRAME_TXSTATUS, 2) \ +- BRCMF_ABSTRACT_ENUM_DEF(MGMT_FRAME_OFFCHAN_DONE, 3) ++ BRCMF_ABSTRACT_ENUM_DEF(MGMT_FRAME_OFFCHAN_DONE, 3) \ ++ BRCMF_ENUM_DEF(ULP, 146) + + #define BRCMF_ENUM_DEF(id, val) \ + BRCMF_E_##id = (val), +@@ -106,6 +107,12 @@ struct brcmf_cfg80211_info; + /* firmware event codes sent by the dongle */ + enum brcmf_fweh_event_code { + BRCMF_FWEH_EVENT_ENUM_DEFLIST ++ ++ /* this determines event mask length which must match ++ * minimum length check in device firmware so it is ++ * hard-coded here. ++ */ ++ BRCMF_E_LAST + }; + #undef BRCMF_ENUM_DEF + +@@ -284,6 +291,28 @@ struct brcmf_if_event { + u8 role; + }; + ++enum event_msgs_ext_command { ++ EVENTMSGS_NONE = 0, ++ EVENTMSGS_SET_BIT = 1, ++ EVENTMSGS_RESET_BIT = 2, ++ EVENTMSGS_SET_MASK = 3 ++}; ++ ++#define EVENTMSGS_VER 1 ++#define EVENTMSGS_EXT_STRUCT_SIZE offsetof(struct eventmsgs_ext, mask[0]) ++ ++/* len- for SET it would be mask size from the application to the firmware */ ++/* for GET it would be actual firmware mask size */ ++/* maxgetsize - is only used for GET. indicate max mask size that the */ ++/* application can read from the firmware */ ++struct eventmsgs_ext { ++ u8 ver; ++ u8 command; ++ u8 len; ++ u8 maxgetsize; ++ u8 mask[1]; ++}; ++ + typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, + const struct brcmf_event_msg *evtmsg, + void *data); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -2210,7 +2210,7 @@ static void brcmf_pcie_setup(struct devi + + init_waitqueue_head(&devinfo->mbdata_resp_wait); + +- ret = brcmf_attach(&devinfo->pdev->dev); ++ ret = brcmf_attach(&devinfo->pdev->dev, true); + if (ret) + goto fail; + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -35,9 +35,12 @@ + #include "core.h" + #include "common.h" + #include "bcdc.h" ++#include "debug.h" ++#include "fwil.h" + + #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) + #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) ++#define ULP_HUDI_PROC_DONE_TIME msecs_to_jiffies(2500) + + /* watermark expressed in number of words */ + #define DEFAULT_F2_WATERMARK 0x8 +@@ -325,7 +328,16 @@ struct rte_console { + + #define KSO_WAIT_US 50 + #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) +-#define BRCMF_SDIO_MAX_ACCESS_ERRORS 5 ++#define BRCMF_SDIO_MAX_ACCESS_ERRORS 20 ++ ++static void brcmf_sdio_firmware_callback(struct device *dev, int err, ++ struct brcmf_fw_request *fwreq); ++static struct brcmf_fw_request * ++ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus); ++static int brcmf_sdio_f2_ready(struct brcmf_sdio *bus); ++static int brcmf_ulp_event_notify(struct brcmf_if *ifp, ++ const struct brcmf_event_msg *evtmsg, ++ void *data); + + #ifdef DEBUG + /* Device console log buffer state */ +@@ -1105,7 +1117,7 @@ static void brcmf_sdio_get_console_addr( + } + #endif /* DEBUG */ + +-static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus) ++static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus, u32 *hmbd) + { + struct brcmf_sdio_dev *sdiod = bus->sdiodev; + struct brcmf_core *core = bus->sdio_core; +@@ -1194,6 +1206,9 @@ static u32 brcmf_sdio_hostmail(struct br + HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) + brcmf_err("Unknown mailbox data content: 0x%02x\n", + hmb_data); ++ /* Populate hmb_data if argument is passed for DS1 check later */ ++ if (hmbd) ++ *hmbd = hmb_data; + + return intstatus; + } +@@ -2580,6 +2595,182 @@ static int brcmf_sdio_intr_rstatus(struc + return ret; + } + ++/* This Function is used to retrieve important ++ * details from dongle related to ULP mode Mostly ++ * values/SHM details that will be vary depending ++ * on the firmware branches ++ */ ++static void ++brcmf_sdio_ulp_preinit(struct device *dev) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ struct brcmf_if *ifp = bus_if->drvr->iflist[0]; ++ ++ brcmf_dbg(ULP, "Enter\n"); ++ ++ /* Query ulp_sdioctrl iovar to get the ULP related SHM offsets */ ++ brcmf_fil_iovar_data_get(ifp, "ulp_sdioctrl", ++ &sdiodev->fmac_ulp.ulp_shm_offset, ++ sizeof(sdiodev->fmac_ulp.ulp_shm_offset)); ++ ++ sdiodev->ulp = false; ++ ++ brcmf_dbg(ULP, "m_ulp_ctrl_sdio[%x] m_ulp_wakeevt_ind [%x]\n", ++ M_DS1_CTRL_SDIO(sdiodev->fmac_ulp), ++ M_WAKEEVENT_IND(sdiodev->fmac_ulp)); ++ brcmf_dbg(ULP, "m_ulp_wakeind [%x]\n", ++ M_ULP_WAKE_IND(sdiodev->fmac_ulp)); ++} ++ ++/* Reinitialize ARM because In DS1 mode ARM got off */ ++static int ++brcmf_sdio_ulp_reinit_fw(struct brcmf_sdio *bus) ++{ ++ struct brcmf_sdio_dev *sdiodev = bus->sdiodev; ++ struct brcmf_fw_request *fwreq; ++ int err = 0; ++ ++ /* After firmware redownload tx/rx seq are reset accordingly ++ * these values are reset on FMAC side tx_max is initially set to 4, ++ * which later is updated by FW. ++ */ ++ bus->tx_seq = 0; ++ bus->rx_seq = 0; ++ bus->tx_max = 4; ++ ++ fwreq = brcmf_sdio_prepare_fw_request(bus); ++ if (!fwreq) ++ return -ENOMEM; ++ ++ err = brcmf_fw_get_firmwares(sdiodev->dev, fwreq, ++ brcmf_sdio_firmware_callback); ++ if (err != 0) { ++ brcmf_err("async firmware request failed: %d\n", err); ++ kfree(fwreq); ++ } ++ ++ return err; ++} ++ ++/* Check if device is in DS1 mode and handshake with ULP UCODE */ ++static bool ++brcmf_sdio_ulp_pre_redownload_check(struct brcmf_sdio *bus, u32 hmb_data) ++{ ++ struct brcmf_sdio_dev *sdiod = bus->sdiodev; ++ int err = 0; ++ u32 value = 0; ++ u32 val32, ulp_wake_ind, wowl_wake_ind; ++ int reg_addr; ++ unsigned long timeout; ++ struct brcmf_ulp *fmac_ulp = &bus->sdiodev->fmac_ulp; ++ int i = 0; ++ ++ /* If any host mail box data is present, ignore DS1 exit sequence */ ++ if (hmb_data) ++ return false; ++ /* Skip if DS1 Exit is already in progress ++ * This can happen if firmware download is taking more time ++ */ ++ if (fmac_ulp->ulp_state == FMAC_ULP_TRIGGERED) ++ return false; ++ ++ value = brcmf_sdiod_func0_rb(sdiod, SDIO_CCCR_IOEx, &err); ++ ++ if (value == SDIO_FUNC_ENABLE_1) { ++ brcmf_dbg(ULP, "GOT THE INTERRUPT FROM UCODE\n"); ++ sdiod->ulp = true; ++ fmac_ulp->ulp_state = FMAC_ULP_TRIGGERED; ++ ulp_wake_ind = D11SHM_RDW(sdiod, ++ M_ULP_WAKE_IND(sdiod->fmac_ulp), ++ &err); ++ wowl_wake_ind = D11SHM_RDW(sdiod, ++ M_WAKEEVENT_IND(sdiod->fmac_ulp), ++ &err); ++ ++ brcmf_dbg(ULP, "wowl_wake_ind: 0x%08x, ulp_wake_ind: 0x%08x state %s\n", ++ wowl_wake_ind, ulp_wake_ind, (fmac_ulp->ulp_state) ? ++ "DS1 Exit Triggered" : "IDLE State"); ++ ++ if (wowl_wake_ind || ulp_wake_ind) { ++ /* RX wake Don't do anything. ++ * Just bail out and re-download firmware. ++ */ ++ /* Print out PHY TX error block when bit 9 set */ ++ if ((ulp_wake_ind & C_DS1_PHY_TXERR) && ++ M_DS1_PHYTX_ERR_BLK(sdiod->fmac_ulp)) { ++ brcmf_err("Dump PHY TX Error SHM Locations\n"); ++ for (i = 0; i < PHYTX_ERR_BLK_SIZE; i++) { ++ pr_err("0x%x", ++ D11SHM_RDW(sdiod, ++ (M_DS1_PHYTX_ERR_BLK(sdiod->fmac_ulp) + ++ (i * 2)), &err)); ++ } ++ brcmf_err("\n"); ++ } ++ } else { ++ /* TX wake negotiate with MAC */ ++ brcmf_dbg(ULP, "M_DS1_CTRL_SDIO: 0x%08x\n", ++ (u32)D11SHM_RDW(sdiod, ++ M_DS1_CTRL_SDIO(sdiod->fmac_ulp), ++ &err)); ++ val32 = D11SHM_RD(sdiod, ++ M_DS1_CTRL_SDIO(sdiod->fmac_ulp), ++ &err); ++ D11SHM_WR(sdiod, M_DS1_CTRL_SDIO(sdiod->fmac_ulp), ++ val32, (C_DS1_CTRL_SDIO_DS1_EXIT | ++ C_DS1_CTRL_REQ_VALID), &err); ++ val32 = D11REG_RD(sdiod, D11_MACCONTROL_REG, &err); ++ val32 = val32 | D11_MACCONTROL_REG_WAKE; ++ D11REG_WR(sdiod, D11_MACCONTROL_REG, val32, &err); ++ ++ /* Poll for PROC_DONE to be set by ucode */ ++ value = D11SHM_RDW(sdiod, ++ M_DS1_CTRL_SDIO(sdiod->fmac_ulp), ++ &err); ++ /* Wait here (polling) for C_DS1_CTRL_PROC_DONE */ ++ timeout = jiffies + ULP_HUDI_PROC_DONE_TIME; ++ while (!(value & C_DS1_CTRL_PROC_DONE)) { ++ value = D11SHM_RDW(sdiod, ++ M_DS1_CTRL_SDIO(sdiod->fmac_ulp), ++ &err); ++ if (time_after(jiffies, timeout)) ++ break; ++ usleep_range(1000, 2000); ++ } ++ brcmf_dbg(ULP, "M_DS1_CTRL_SDIO: 0x%08x\n", ++ (u32)D11SHM_RDW(sdiod, ++ M_DS1_CTRL_SDIO(sdiod->fmac_ulp), &err)); ++ value = D11SHM_RDW(sdiod, ++ M_DS1_CTRL_SDIO(sdiod->fmac_ulp), ++ &err); ++ if (!(value & C_DS1_CTRL_PROC_DONE)) { ++ brcmf_err("Timeout Failed to enter DS1 Exit state!\n"); ++ return false; ++ } ++ } ++ ++ ulp_wake_ind = D11SHM_RDW(sdiod, ++ M_ULP_WAKE_IND(sdiod->fmac_ulp), ++ &err); ++ wowl_wake_ind = D11SHM_RDW(sdiod, ++ M_WAKEEVENT_IND(sdiod->fmac_ulp), ++ &err); ++ brcmf_dbg(ULP, "wowl_wake_ind: 0x%08x, ulp_wake_ind: 0x%08x\n", ++ wowl_wake_ind, ulp_wake_ind); ++ reg_addr = CORE_CC_REG( ++ brcmf_chip_get_pmu(bus->ci)->base, min_res_mask); ++ brcmf_sdiod_writel(sdiod, reg_addr, ++ DEFAULT_43012_MIN_RES_MASK, &err); ++ if (err) ++ brcmf_err("min_res_mask failed\n"); ++ ++ return true; ++ } ++ ++ return false; ++} ++ + static void brcmf_sdio_dpc(struct brcmf_sdio *bus) + { + struct brcmf_sdio_dev *sdiod = bus->sdiodev; +@@ -2651,8 +2842,11 @@ static void brcmf_sdio_dpc(struct brcmf_ + + /* Handle host mailbox indication */ + if (intstatus & I_HMB_HOST_INT) { ++ u32 hmb_data = 0; + intstatus &= ~I_HMB_HOST_INT; +- intstatus |= brcmf_sdio_hostmail(bus); ++ intstatus |= brcmf_sdio_hostmail(bus, &hmb_data); ++ if (brcmf_sdio_ulp_pre_redownload_check(bus, hmb_data)) ++ brcmf_sdio_ulp_reinit_fw(bus); + } + + sdio_release_host(bus->sdiodev->func1); +@@ -2697,7 +2891,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + brcmf_sdio_clrintr(bus); + + if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && +- txctl_ok(bus)) { ++ txctl_ok(bus) && brcmf_sdio_f2_ready(bus)) { + sdio_claim_host(bus->sdiodev->func1); + if (bus->ctrl_frame_stat) { + err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, +@@ -3567,6 +3761,10 @@ static int brcmf_sdio_bus_preinit(struct + if (err < 0) + goto done; + ++ /* initialize SHM address from firmware for DS1 */ ++ if (!bus->sdiodev->ulp) ++ brcmf_sdio_ulp_preinit(dev); ++ + bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; + if (sdiodev->sg_support) { + bus->txglom = false; +@@ -4217,7 +4415,7 @@ static void brcmf_sdio_firmware_callback + u8 saveclk, bpreq; + u8 devctl; + +- brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); ++ brcmf_dbg(ULP, "Enter: dev=%s, err=%d\n", dev_name(dev), err); + + if (err) + goto fail; +@@ -4394,12 +4592,25 @@ static void brcmf_sdio_firmware_callback + } + + /* Attach to the common layer, reserve hdr space */ +- err = brcmf_attach(sdiod->dev); ++ err = brcmf_attach(sdiod->dev, !bus->sdiodev->ulp); + if (err != 0) { + brcmf_err("brcmf_attach failed\n"); + goto free; + } + ++ /* Register for ULP events */ ++ if (sdiod->func1->device == SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012) ++ brcmf_fweh_register(bus_if->drvr, BRCMF_E_ULP, ++ brcmf_ulp_event_notify); ++ ++ if (bus->sdiodev->ulp) { ++ /* For ULP, after firmware redownload complete ++ * set ULP state to IDLE ++ */ ++ if (bus->sdiodev->fmac_ulp.ulp_state == FMAC_ULP_TRIGGERED) ++ bus->sdiodev->fmac_ulp.ulp_state = FMAC_ULP_IDLE; ++ } ++ + /* ready */ + return; + +@@ -4646,3 +4857,40 @@ int brcmf_sdio_sleep(struct brcmf_sdio * + + return ret; + } ++ ++/* Check F2 Ready bit before sending data to Firmware */ ++static int ++brcmf_sdio_f2_ready(struct brcmf_sdio *bus) ++{ ++ int ret = -1; ++ int iordy_status = 0; ++ ++ sdio_claim_host(bus->sdiodev->func1); ++ /* Read the status of IOR2 */ ++ iordy_status = brcmf_sdiod_func0_rb(bus->sdiodev, SDIO_CCCR_IORx, NULL); ++ ++ sdio_release_host(bus->sdiodev->func1); ++ ret = iordy_status & SDIO_FUNC_ENABLE_2; ++ return ret; ++} ++ ++static int brcmf_ulp_event_notify(struct brcmf_if *ifp, ++ const struct brcmf_event_msg *evtmsg, ++ void *data) ++{ ++ int err = 0; ++ struct brcmf_bus *bus_if = ifp->drvr->bus_if; ++ struct brcmf_sdio_dev *sdiodev; ++ struct brcmf_sdio *bus; ++ struct brcmf_ulp_event *ulp_event = (struct brcmf_ulp_event *)data; ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ bus = sdiodev->bus; ++ ++ brcmf_dbg(ULP, "Chip went to DS1 state : action %d\n", ++ ulp_event->ulp_dongle_action); ++ if (ulp_event->ulp_dongle_action == FMAC_ULP_ENTRY) ++ bus->sdiodev->fmac_ulp.ulp_state = FMAC_ULP_ENTRY_RECV; ++ ++ return err; ++} +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -165,6 +165,35 @@ struct brcmf_sdreg { + struct brcmf_sdio; + struct brcmf_sdiod_freezer; + ++/* ULP SHM Offsets info */ ++struct ulp_shm_info { ++ u32 m_ulp_ctrl_sdio; ++ u32 m_ulp_wakeevt_ind; ++ u32 m_ulp_wakeind; ++ u32 m_ulp_phytxblk; ++}; ++ ++/* FMAC ULP state machine */ ++#define FMAC_ULP_IDLE (0) ++#define FMAC_ULP_ENTRY_RECV (1) ++#define FMAC_ULP_TRIGGERED (2) ++ ++/* BRCMF_E_ULP event data */ ++#define FMAC_ULP_EVENT_VERSION 1 ++#define FMAC_ULP_DISABLE_CONSOLE 1 /* Disable console */ ++#define FMAC_ULP_UCODE_DOWNLOAD 2 /* Download ULP ucode file */ ++#define FMAC_ULP_ENTRY 3 /* Inform ulp entry to Host */ ++ ++struct brcmf_ulp { ++ uint ulp_state; ++ struct ulp_shm_info ulp_shm_offset; ++}; ++ ++struct brcmf_ulp_event { ++ u16 version; ++ u16 ulp_dongle_action; ++}; ++ + struct brcmf_sdio_dev { + struct sdio_func *func1; + struct sdio_func *func2; +@@ -193,6 +222,8 @@ struct brcmf_sdio_dev { + enum brcmf_sdiod_state state; + struct brcmf_sdiod_freezer *freezer; + const struct firmware *clm_fw; ++ struct brcmf_ulp fmac_ulp; ++ bool ulp; + }; + + /* sdio core registers */ +@@ -367,4 +398,83 @@ void brcmf_sdio_wowl_config(struct devic + int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep); + void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus); + ++/* SHM offsets */ ++#define M_DS1_CTRL_SDIO(ptr) ((ptr).ulp_shm_offset.m_ulp_ctrl_sdio) ++#define M_WAKEEVENT_IND(ptr) ((ptr).ulp_shm_offset.m_ulp_wakeevt_ind) ++#define M_ULP_WAKE_IND(ptr) ((ptr).ulp_shm_offset.m_ulp_wakeind) ++#define M_DS1_PHYTX_ERR_BLK(ptr) ((ptr).ulp_shm_offset.m_ulp_phytxblk) ++ ++#define D11_BASE_ADDR 0x18001000 ++#define D11_AXI_BASE_ADDR 0xE8000000 ++#define D11_SHM_BASE_ADDR (D11_AXI_BASE_ADDR + 0x4000) ++ ++#define D11REG_ADDR(offset) (D11_BASE_ADDR + (offset)) ++#define D11IHR_ADDR(offset) (D11_AXI_BASE_ADDR + 0x400 + (2 * (offset))) ++#define D11SHM_ADDR(offset) (D11_SHM_BASE_ADDR + (offset)) ++ ++/* MacControl register */ ++#define D11_MACCONTROL_REG D11REG_ADDR(0x120) ++#define D11_MACCONTROL_REG_WAKE 0x4000000 ++ ++/* HUDI Sequence SHM bits */ ++#define C_DS1_CTRL_SDIO_DS1_SLEEP 0x1 ++#define C_DS1_CTRL_SDIO_MAC_ON 0x2 ++#define C_DS1_CTRL_SDIO_RADIO_PHY_ON 0x4 ++#define C_DS1_CTRL_SDIO_DS1_EXIT 0x8 ++#define C_DS1_CTRL_PROC_DONE 0x100 ++#define C_DS1_CTRL_REQ_VALID 0x200 ++ ++/* M_ULP_WAKEIND bits */ ++#define C_WATCHDOG_EXPIRY BIT(0) ++#define C_FCBS_ERROR BIT(1) ++#define C_RETX_FAILURE BIT(2) ++#define C_HOST_WAKEUP BIT(3) ++#define C_INVALID_FCBS_BLOCK BIT(4) ++#define C_HUDI_DS1_EXIT BIT(5) ++#define C_LOB_SLEEP BIT(6) ++#define C_DS1_PHY_TXERR BIT(9) ++#define C_DS1_WAKE_TIMER BIT(10) ++ ++#define PHYTX_ERR_BLK_SIZE 18 ++#define D11SHM_FIRST2BYTE_MASK 0xFFFF0000 ++#define D11SHM_SECOND2BYTE_MASK 0x0000FFFF ++#define D11SHM_2BYTE_SHIFT 16 ++ ++#define D11SHM_RD(sdh, offset, ret) \ ++ brcmf_sdiod_readl(sdh, D11SHM_ADDR(offset), ret) ++ ++/* SHM Read is motified based on SHM 4 byte alignment as SHM size is 2 bytes and ++ * 2 byte is currently not working on FMAC ++ * If SHM address is not 4 byte aligned, then right shift by 16 ++ * otherwise, mask the first two MSB bytes ++ * Suppose data in address 7260 is 0x440002 and it is 4 byte aligned ++ * Correct SHM value is 0x2 for this SHM offset and next SHM value is 0x44 ++ */ ++#define D11SHM_RDW(sdh, offset, ret) \ ++ ((offset % 4) ? \ ++ (brcmf_sdiod_readl(sdh, D11SHM_ADDR(offset), ret) \ ++ >> D11SHM_2BYTE_SHIFT) : \ ++ (brcmf_sdiod_readl(sdh, D11SHM_ADDR(offset), ret) \ ++ & D11SHM_SECOND2BYTE_MASK)) ++ ++/* SHM is of size 2 bytes, 4 bytes write will overwrite other SHM's ++ * First read 4 bytes and then clear the required two bytes based on ++ * 4 byte alignment, then update the required value and write the ++ * 4 byte value now ++ */ ++#define D11SHM_WR(sdh, offset, val, mask, ret) \ ++ do { \ ++ if ((offset) % 4) \ ++ val = (val & D11SHM_SECOND2BYTE_MASK) | \ ++ ((mask) << D11SHM_2BYTE_SHIFT); \ ++ else \ ++ val = (mask) | (val & D11SHM_FIRST2BYTE_MASK); \ ++ brcmf_sdiod_writel(sdh, D11SHM_ADDR(offset), val, ret); \ ++ } while (0) ++#define D11REG_WR(sdh, addr, val, ret) \ ++ brcmf_sdiod_writel(sdh, addr, val, ret) ++ ++#define D11REG_RD(sdh, addr, ret) \ ++ brcmf_sdiod_readl(sdh, addr, ret) ++ + #endif /* BRCMFMAC_SDIO_H */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1211,7 +1211,7 @@ static void brcmf_usb_probe_phase2(struc + goto error; + + /* Attach to the common driver interface */ +- ret = brcmf_attach(devinfo->dev); ++ ret = brcmf_attach(devinfo->dev, true); + if (ret) + goto error; + +@@ -1291,7 +1291,7 @@ static int brcmf_usb_probe_cb(struct brc + ret = brcmf_alloc(devinfo->dev, devinfo->settings); + if (ret) + goto fail; +- ret = brcmf_attach(devinfo->dev); ++ ret = brcmf_attach(devinfo->dev, true); + if (ret) + goto fail; + /* we are done */ +--- a/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h +@@ -308,4 +308,6 @@ struct chipcregs { + */ + #define PMU_MAX_TRANSITION_DLY 15000 + ++#define DEFAULT_43012_MIN_RES_MASK 0x0f8bfe77 ++ + #endif /* _SBCHIPC_H */ diff --git a/patches/brcm/870-05-rpi-6.12-brcmfmac-Fix-interoperating-DPP-and-other-encryption.patch b/patches/brcm/870-05-rpi-6.12-brcmfmac-Fix-interoperating-DPP-and-other-encryption.patch new file mode 100644 index 0000000..23a9c62 --- /dev/null +++ b/patches/brcm/870-05-rpi-6.12-brcmfmac-Fix-interoperating-DPP-and-other-encryption.patch @@ -0,0 +1,129 @@ +From 4c1d4af0ac83705828dd11fded409163a87ea515 Mon Sep 17 00:00:00 2001 +From: Kurt Lee +Date: Thu, 20 Aug 2020 03:07:02 -0500 +Subject: [PATCH] brcmfmac: Fix interoperating DPP and other encryption network + access + +1. If firmware supports 4-way handshake offload but not supports DPP +4-way offload, when user first connects encryption network, driver will +set "sup_wpa 1" to firmware, but it will further result in DPP +connection failure since firmware won't send EAPOL frame to host. + +2. Fix DPP AP mode handling action frames. + +3. For some firmware without fwsup support, the join procedure will be +skipped due to "sup_wpa" iovar returning not-support. Check the fwsup +feature before do such iovar. + +Signed-off-by: Kurt Lee +Signed-off-by: Double Lo +Signed-off-by: Chi-hsien Lin +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 67 ++++++++++--------- + .../broadcom/brcm80211/brcmfmac/p2p.c | 5 ++ + 2 files changed, 42 insertions(+), 30 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2496,43 +2496,50 @@ brcmf_cfg80211_connect(struct wiphy *wip + goto done; + } + +- if (sme->crypto.psk && +- profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { +- if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) { +- err = -EINVAL; +- goto done; ++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) { ++ if (sme->crypto.psk) { ++ if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { ++ if (WARN_ON(profile->use_fwsup != ++ BRCMF_PROFILE_FWSUP_NONE)) { ++ err = -EINVAL; ++ goto done; ++ } ++ brcmf_dbg(INFO, "using PSK offload\n"); ++ profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK; ++ } ++ } else { ++ profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE; + } +- brcmf_dbg(INFO, "using PSK offload\n"); +- profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK; +- } + +- if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { +- /* enable firmware supplicant for this interface */ +- err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); +- if (err < 0) { +- bphy_err(drvr, "failed to enable fw supplicant\n"); +- goto done; ++ if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { ++ /* enable firmware supplicant for this interface */ ++ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); ++ if (err < 0) { ++ bphy_err(drvr, "failed to enable fw supplicant\n"); ++ goto done; ++ } ++ } else { ++ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0); + } +- } + +- if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) +- err = brcmf_set_pmk(ifp, sme->crypto.psk, +- BRCMF_WSEC_MAX_PSK_LEN); +- else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) { +- /* clean up user-space RSNE */ +- err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0); +- if (err) { +- bphy_err(drvr, "failed to clean up user-space RSNE\n"); +- goto done; +- } +- err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); +- if (!err && sme->crypto.psk) ++ if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) { + err = brcmf_set_pmk(ifp, sme->crypto.psk, + BRCMF_WSEC_MAX_PSK_LEN); ++ } else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) { ++ /* clean up user-space RSNE */ ++ err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0); ++ if (err) { ++ bphy_err(drvr, "failed to clean up user-space RSNE\n"); ++ goto done; ++ } ++ err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); ++ if (!err && sme->crypto.psk) ++ err = brcmf_set_pmk(ifp, sme->crypto.psk, ++ BRCMF_WSEC_MAX_PSK_LEN); ++ } ++ if (err) ++ goto done; + } +- if (err) +- goto done; +- + /* Join with specific BSSID and cached SSID + * If SSID is zero join based on BSSID only + */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +@@ -1281,6 +1281,10 @@ static s32 brcmf_p2p_abort_action_frame( + brcmf_dbg(TRACE, "Enter\n"); + + vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; ++ ++ if (!vif) ++ vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; ++ + err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val, + sizeof(s32)); + if (err) +@@ -1826,6 +1830,7 @@ bool brcmf_p2p_send_action_frame(struct + /* validate channel and p2p ies */ + if (config_af_params.search_channel && + IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) && ++ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { + afx_hdl = &p2p->afx_hdl; + afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel); diff --git a/patches/brcm/870-06-rpi-6.12-brcmfmac-Include-modinfo-for-43456-CLM-blob.patch b/patches/brcm/870-06-rpi-6.12-brcmfmac-Include-modinfo-for-43456-CLM-blob.patch new file mode 100644 index 0000000..f90406f --- /dev/null +++ b/patches/brcm/870-06-rpi-6.12-brcmfmac-Include-modinfo-for-43456-CLM-blob.patch @@ -0,0 +1,26 @@ +From 0ff7f575b657b3fdfbd6902b68a28548208f4d36 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 8 May 2025 16:55:27 +0100 +Subject: [PATCH] wifi: brcmfmac: Include modinfo for 43456 CLM blob + +Listing firmware files in the brcmfmac modinfo helps with e.g. initramfs +creation. + +See: https://github.com/raspberrypi/linux/issues/6828 + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -631,7 +631,7 @@ BRCMF_FW_CLM_DEF(43430A1, "brcmfmac43430 + BRCMF_FW_DEF(43430B0, "brcmfmac43430b0-sdio"); + BRCMF_FW_CLM_DEF(43439, "brcmfmac43439-sdio"); + BRCMF_FW_CLM_DEF(43455, "brcmfmac43455-sdio"); +-BRCMF_FW_DEF(43456, "brcmfmac43456-sdio"); ++BRCMF_FW_CLM_DEF(43456, "brcmfmac43456-sdio"); + BRCMF_FW_CLM_DEF(4354, "brcmfmac4354-sdio"); + BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-sdio"); + BRCMF_FW_DEF(4359, "brcmfmac4359-sdio"); diff --git a/patches/brcm/871-brcmfmac-disable-dump_survey-on-bcm2835.patch b/patches/brcm/871-brcmfmac-disable-dump_survey-on-bcm2835.patch new file mode 100644 index 0000000..8bd63cd --- /dev/null +++ b/patches/brcm/871-brcmfmac-disable-dump_survey-on-bcm2835.patch @@ -0,0 +1,38 @@ +brcmfmac: disable dump_survey on Raspberry Pi + +Enabling this causes slow iwinfo calls on Raspberry Pi and LuCI slows down +when wireless is enabled. +https://github.com/openwrt/openwrt/issues/14013 + +Signed-off-by: Álvaro Fernández Rojas +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -8002,6 +8002,7 @@ static s32 brcmf_translate_country_code( + return 0; + } + ++#if !defined(CONFIG_ARCH_BCM2835) + static int + brcmf_parse_dump_obss(char *buf, struct brcmf_dump_survey *survey) + { +@@ -8224,6 +8225,7 @@ exit: + brcmf_set_mpc(ifp, 1); + return err; + } ++#endif /* CONFIG_ARCH_BCM2835 */ + + static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *req) +@@ -8390,8 +8392,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802 + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) + ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; + #endif ++#if !defined(CONFIG_ARCH_BCM2835) + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DUMP_OBSS)) + ops->dump_survey = brcmf_cfg80211_dump_survey; ++#endif /* CONFIG_ARCH_BCM2835 */ + + err = wiphy_register(wiphy); + if (err < 0) { diff --git a/patches/build/000-fix_kconfig.patch b/patches/build/000-fix_kconfig.patch new file mode 100644 index 0000000..3987aae --- /dev/null +++ b/patches/build/000-fix_kconfig.patch @@ -0,0 +1,14 @@ +--- a/kconf/Makefile ++++ b/kconf/Makefile +@@ -1,9 +1,9 @@ +-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer ++CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS + + LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o + + conf: conf.o zconf.tab.o +-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE ++mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) + mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC)) + mconf: CFLAGS += $(mconf_CFLAGS) + diff --git a/patches/build/001-fix_build.patch b/patches/build/001-fix_build.patch new file mode 100644 index 0000000..085eae3 --- /dev/null +++ b/patches/build/001-fix_build.patch @@ -0,0 +1,168 @@ +--- a/Makefile ++++ b/Makefile +@@ -5,7 +5,7 @@ + ifeq ($(KERNELRELEASE),) + + MAKEFLAGS += --no-print-directory +-SHELL := /bin/bash ++SHELL := /usr/bin/env bash + BACKPORT_DIR := $(shell pwd) + + KMODDIR ?= updates +@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/ + KERNEL_CONFIG := $(KLIB_BUILD)/.config + KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile + CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//') ++STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5) + + export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG + +@@ -36,7 +37,8 @@ mrproper: + @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel + @rm -f backport-include/backport/autoconf.h + +-.DEFAULT: ++.SILENT: $(STAMP_KERNEL_CONFIG) ++$(STAMP_KERNEL_CONFIG): + @set -e ; test -f local-symbols || ( \ + echo "/--------------" ;\ + echo "| You shouldn't run make in the backports tree, but only in" ;\ +@@ -60,57 +62,62 @@ mrproper: + echo "| (that isn't currently running.)" ;\ + echo "\\--" ;\ + false) +- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\ +- then \ +- echo -n "Generating local configuration database from kernel ..." ;\ +- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \ +- while read l ; do \ +- if [ "$${l:0:7}" != "CONFIG_" ] ; then \ +- continue ;\ +- fi ;\ +- l=$${l:7} ;\ +- n=$${l%%=*} ;\ +- v=$${l#*=} ;\ +- if [ "$$v" = "m" ] ; then \ +- echo config $$n ;\ +- echo ' tristate' ;\ +- elif [ "$$v" = "y" ] ; then \ +- echo config $$n ;\ +- echo ' bool' ;\ +- else \ +- continue ;\ +- fi ;\ +- echo " default $$v" ;\ +- echo "" ;\ +- done \ +- ) > Kconfig.kernel ;\ +- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \ +- kernelversion | sed 's/^\(\([3-6]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\ +- test "$$kver" != "" || echo "Kernel version parse failed!" ;\ +- test "$$kver" != "" ;\ +- kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\ +- kvers="$$kvers $$(seq 0 19 | sed 's/^/5./')" ;\ +- kvers="$$kvers $$(seq 0 20 | sed 's/^/6./')" ;\ +- print=0 ;\ +- for v in $$kvers ; do \ +- if [ "$$print" = "1" ] ; then \ +- echo config KERNEL_$$(echo $$v | tr . _) ;\ +- echo " def_bool y" ;\ +- fi ;\ +- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\ +- done > Kconfig.versions ;\ +- # RHEL as well, sadly we need to grep for it ;\ +- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \ +- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ +- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \ +- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ +- for v in $$(seq 0 $$RHEL_MINOR) ; do \ +- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\ +- echo " def_bool y" ;\ +- done >> Kconfig.versions ;\ +- echo " done." ;\ +- fi ;\ +- echo "$(CONFIG_MD5)" > .kernel_config_md5 ++ @rm -f .kernel_config_md5_* ++ @touch $@ ++ ++Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols ++ @printf "Generating local configuration database from kernel ..." ++ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \ ++ while read l ; do \ ++ if [ "$${l:0:7}" != "CONFIG_" ] ; then \ ++ continue ;\ ++ fi ;\ ++ l=$${l:7} ;\ ++ n=$${l%%=*} ;\ ++ v=$${l#*=} ;\ ++ if [ "$$v" = "m" ] ; then \ ++ echo config $$n ;\ ++ echo ' tristate' ;\ ++ elif [ "$$v" = "y" ] ; then \ ++ echo config $$n ;\ ++ echo ' bool' ;\ ++ else \ ++ continue ;\ ++ fi ;\ ++ echo " default $$v" ;\ ++ echo "" ;\ ++ done \ ++ ) > $@ ++ @echo " done." ++ ++Kconfig.versions: Kconfig.kernel ++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \ ++ kernelversion | sed 's/^\(\([3-6]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\ ++ test "$$kver" != "" || echo "Kernel version parse failed!" ;\ ++ test "$$kver" != "" ;\ ++ kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\ ++ kvers="$$kvers $$(seq 0 19 | sed 's/^/5./')" ;\ ++ kvers="$$kvers $$(seq 0 20 | sed 's/^/6./')" ;\ ++ print=0 ;\ ++ for v in $$kvers ; do \ ++ if [ "$$print" = "1" ] ; then \ ++ echo config KERNEL_$$(echo $$v | tr . _) ;\ ++ echo " def_bool y" ;\ ++ fi ;\ ++ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\ ++ done > Kconfig.versions ;\ ++ # RHEL as well, sadly we need to grep for it ;\ ++ RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \ ++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ ++ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \ ++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ ++ for v in $$(seq 0 $$RHEL_MINOR) ; do \ ++ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\ ++ echo " def_bool y" ;\ ++ done >> $@ ++ ++.DEFAULT: ++ @$(MAKE) Kconfig.versions + @$(MAKE) -f Makefile.real "$@" + + .PHONY: defconfig-help +--- a/Makefile.real ++++ b/Makefile.real +@@ -59,7 +59,7 @@ defconfig-%:: + + backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel + @$(MAKE) oldconfig +- @echo -n "Building backport-include/backport/autoconf.h ..." ++ @printf "Building backport-include/backport/autoconf.h ..." + @grep -f local-symbols .config | ( \ + echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\ + echo "#define COMPAT_AUTOCONF_INCLUDED" ;\ +@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c + esac ;\ + done ;\ + echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\ +- ) > backport-include/backport/autoconf.h ++ ) > $@.new ++ @if cmp -s $@ $@.new; then \ ++ rm -f $@.new; \ ++ else \ ++ mv $@.new $@; \ ++ fi + @echo " done." + + .PHONY: modules diff --git a/patches/build/002-change_allconfig.patch b/patches/build/002-change_allconfig.patch new file mode 100644 index 0000000..368725d --- /dev/null +++ b/patches/build/002-change_allconfig.patch @@ -0,0 +1,64 @@ +--- a/kconf/conf.c ++++ b/kconf/conf.c +@@ -598,40 +598,12 @@ int main(int ac, char **av) + case oldconfig: + case listnewconfig: + case olddefconfig: +- conf_read(NULL); +- break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: +- name = getenv("KCONFIG_ALLCONFIG"); +- if (!name) +- break; +- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { +- if (conf_read_simple(name, S_DEF_USER)) { +- fprintf(stderr, +- _("*** Can't read seed configuration \"%s\"!\n"), +- name); +- exit(1); +- } +- break; +- } +- switch (input_mode) { +- case allnoconfig: name = "allno.config"; break; +- case allyesconfig: name = "allyes.config"; break; +- case allmodconfig: name = "allmod.config"; break; +- case alldefconfig: name = "alldef.config"; break; +- case randconfig: name = "allrandom.config"; break; +- default: break; +- } +- if (conf_read_simple(name, S_DEF_USER) && +- conf_read_simple("all.config", S_DEF_USER)) { +- fprintf(stderr, +- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), +- name); +- exit(1); +- } ++ conf_read(NULL); + break; + default: + break; +--- a/kconf/confdata.c ++++ b/kconf/confdata.c +@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_ + } + bool has_changed = false; + ++ sym_clear_all_valid(); ++ + for_all_symbols(i, sym) { + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) + continue; +@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_ + + } + +- sym_clear_all_valid(); +- + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several diff --git a/patches/build/003-remove_bogus_modparams.patch b/patches/build/003-remove_bogus_modparams.patch new file mode 100644 index 0000000..aa26c8c --- /dev/null +++ b/patches/build/003-remove_bogus_modparams.patch @@ -0,0 +1,34 @@ +--- a/compat/main.c ++++ b/compat/main.c +@@ -19,31 +19,6 @@ MODULE_LICENSE("GPL"); + #error "You need a CPTCFG_VERSION" + #endif + +-static char *backported_kernel_name = CPTCFG_KERNEL_NAME; +- +-module_param(backported_kernel_name, charp, 0400); +-MODULE_PARM_DESC(backported_kernel_name, +- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")"); +- +-#ifdef BACKPORTS_GIT_TRACKED +-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED; +-module_param(backports_tracker_id, charp, 0400); +-MODULE_PARM_DESC(backports_tracker_id, +- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")"); +-#else +-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION; +-static char *backports_version = CPTCFG_VERSION; +- +-module_param(backported_kernel_version, charp, 0400); +-MODULE_PARM_DESC(backported_kernel_version, +- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")"); +- +-module_param(backports_version, charp, 0400); +-MODULE_PARM_DESC(backports_version, +- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")"); +- +-#endif +- + void backport_dependency_symbol(void) + { + } diff --git a/patches/build/004-fix-kconf-compiling.patch b/patches/build/004-fix-kconf-compiling.patch new file mode 100644 index 0000000..8bae836 --- /dev/null +++ b/patches/build/004-fix-kconf-compiling.patch @@ -0,0 +1,47 @@ +--- a/Makefile.real ++++ b/Makefile.real +@@ -6,6 +6,18 @@ else + export BACKPORTS_GIT_TRACKER_DEF= + endif + ++ifneq ($(LLVM),) ++ifneq ($(filter %/,$(LLVM)),) ++LLVM_PREFIX := $(LLVM) ++else ifneq ($(filter -%,$(LLVM)),) ++LLVM_SUFFIX := $(LLVM) ++endif ++ ++HOSTCC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX) ++else ++HOSTCC = gcc ++endif ++ + # disable built-in rules for this file + .SUFFIXES: + +@@ -24,21 +36,21 @@ listnewconfig oldaskconfig oldconfig \ + silentoldconfig olddefconfig oldnoconfig \ + allnoconfig allyesconfig allmodconfig \ + alldefconfig randconfig: +- @$(MAKE) -C kconf conf ++ @$(MAKE) -C kconf CC=$(HOSTCC) conf + @./kconf/conf --$@ Kconfig + + .PHONY: usedefconfig + usedefconfig: +- @$(MAKE) -C kconf conf ++ @$(MAKE) -C kconf CC=$(HOSTCC) conf + @./kconf/conf --defconfig=defconfig Kconfig + + .PHONY: savedefconfig + savedefconfig: +- @$(MAKE) -C kconf conf ++ @$(MAKE) -C kconf CC=$(HOSTCC) conf + @./kconf/conf --savedefconfig=defconfig Kconfig + + defconfig-%:: +- @$(MAKE) -C kconf conf ++ @$(MAKE) -C kconf CC=$(HOSTCC) conf + @./kconf/conf --defconfig=defconfigs/$(@:defconfig-%=%) Kconfig + + .config: diff --git a/patches/build/005-fix-kconf-warnings.patch b/patches/build/005-fix-kconf-warnings.patch new file mode 100644 index 0000000..00e9400 --- /dev/null +++ b/patches/build/005-fix-kconf-warnings.patch @@ -0,0 +1,76 @@ +--- a/kconf/conf.c ++++ b/kconf/conf.c +@@ -86,7 +86,7 @@ static int conf_askvalue(struct symbol * + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) +- printf(_("(NEW) ")); ++ printf("%s", _("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; +@@ -282,7 +282,7 @@ static int conf_choice(struct menu *menu + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) +- printf(_(" (NEW)")); ++ printf("%s", _(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); +@@ -437,7 +437,7 @@ static void check_conf(struct menu *menu + } + } else { + if (!conf_cnt++) +- printf(_("*\n* Restart config...\n*\n")); ++ printf("%s", _("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } +@@ -614,7 +614,7 @@ int main(int ac, char **av) + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, +- _("\n*** The configuration requires explicit update.\n\n")); ++ "%s", _("\n*** The configuration requires explicit update.\n\n")); + return 1; + } + } +@@ -666,22 +666,22 @@ int main(int ac, char **av) + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { +- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); ++ fprintf(stderr, "%s", _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { +- fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); ++ fprintf(stderr, "%s", _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else if (input_mode == savedefconfig) { + if (conf_write_defconfig(defconfig_file)) { +- fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), ++ fprintf(stderr, _("\n*** Error while saving defconfig to: %s\n\n"), + defconfig_file); + return 1; + } + } else if (input_mode != listnewconfig) { + if (conf_write(NULL)) { +- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); ++ fprintf(stderr, "%s", _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } +--- a/kconf/Makefile ++++ b/kconf/Makefile +@@ -17,7 +17,7 @@ clean: + zconf.tab.c: zconf.lex.c + + %.tab.c: %.y +- $(YACC) -o$@ -t -l $< ++ $(YACC) -Wno-yacc -o$@ -t -l $< + + %.lex.c: %.l + $(LEX) -o$@ -L $< diff --git a/patches/build/012-kernel_build_check.patch b/patches/build/012-kernel_build_check.patch new file mode 100644 index 0000000..d225ba1 --- /dev/null +++ b/patches/build/012-kernel_build_check.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -2,7 +2,7 @@ + # Makefile for the output source package + # + +-ifeq ($(KERNELRELEASE),) ++ifeq ($(KERNELVERSION),) + + MAKEFLAGS += --no-print-directory + SHELL := /usr/bin/env bash diff --git a/patches/build/020-intel-mld-compile.patch b/patches/build/020-intel-mld-compile.patch new file mode 100644 index 0000000..b501ec7 --- /dev/null +++ b/patches/build/020-intel-mld-compile.patch @@ -0,0 +1,54 @@ +Fix Intel mld thermal compilation + +Do the same changes done also in iwlwifi/mvm/tt.c in the iwlwifi/mld/thermal.c file. + +This fixes the compilation. + +--- a/drivers/net/wireless/intel/iwlwifi/mld/thermal.c ++++ b/drivers/net/wireless/intel/iwlwifi/mld/thermal.c +@@ -209,9 +209,15 @@ unlock: + return ret; + } + ++#if LINUX_VERSION_IS_GEQ(6,11,0) + static int iwl_mld_tzone_set_trip_temp(struct thermal_zone_device *device, + const struct thermal_trip *trip, + int temp) ++#else ++static int iwl_mld_tzone_set_trip_temp(struct thermal_zone_device *device, ++ int trip, ++ int temp) ++#endif + { + struct iwl_mld *mld = thermal_zone_device_priv(device); + int ret; +@@ -248,18 +254,29 @@ static void iwl_mld_thermal_zone_registe + [0 ... IWL_MAX_DTS_TRIPS - 1] = { + .temperature = THERMAL_TEMP_INVALID, + .type = THERMAL_TRIP_PASSIVE, ++#if LINUX_VERSION_IS_GEQ(6,9,0) + .flags = THERMAL_TRIP_FLAG_RW_TEMP, ++#endif + }, + }; + + BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); + + sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF); ++#if LINUX_VERSION_IS_GEQ(6,9,0) + mld->tzone = + thermal_zone_device_register_with_trips(name, trips, + IWL_MAX_DTS_TRIPS, + mld, &tzone_ops, + NULL, 0, 0); ++#else ++ mld->tzone = ++ thermal_zone_device_register_with_trips(name, trips, ++ IWL_MAX_DTS_TRIPS, 0, ++ mld, &tzone_ops, ++ NULL, 0, 0); ++#endif ++ + if (IS_ERR(mld->tzone)) { + IWL_DEBUG_TEMP(mld, + "Failed to register to thermal zone (err = %ld)\n", diff --git a/patches/build/100-backports-drop-QRTR-and-MHI.patch b/patches/build/100-backports-drop-QRTR-and-MHI.patch new file mode 100644 index 0000000..c9cac82 --- /dev/null +++ b/patches/build/100-backports-drop-QRTR-and-MHI.patch @@ -0,0 +1,76 @@ +From 54e0f9aaf340377fb76acdffee9ec7372c4b70ae Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 17 Oct 2022 11:35:36 +0200 +Subject: [PATCH] backports: drop QRTR and MHI + +Backports currently include QRTR and MHI due to ath11k-pci requiring them, +however this at the same time prevents us from adding ath11k-ahb as it +also requires QRTR however its AHB variant from the kernel will conflict +with the core provided by backports. + +Since MHI also conflicts with existing OpenWrt kmods providing MHI drop +both from backports and use the ones provided by OpenWrt kernel. + +Signed-off-by: Robert Marko +--- + Kconfig.sources | 2 -- + Makefile.kernel | 2 -- + drivers/net/wireless/ath/ath11k/Kconfig | 6 +++--- + local-symbols | 8 -------- + 4 files changed, 3 insertions(+), 15 deletions(-) + +--- a/Kconfig.sources ++++ b/Kconfig.sources +@@ -4,8 +4,6 @@ source "$BACKPORT_DIR/compat/Kconfig" + # these are copied from the kernel + source "$BACKPORT_DIR/net/wireless/Kconfig" + source "$BACKPORT_DIR/net/mac80211/Kconfig" +-source "$BACKPORT_DIR/net/qrtr/Kconfig" +-source "$BACKPORT_DIR/drivers/bus/mhi/Kconfig" + source "$BACKPORT_DIR/drivers/soc/qcom/Kconfig" + source "$BACKPORT_DIR/drivers/net/wireless/Kconfig" + source "$BACKPORT_DIR/drivers/net/usb/Kconfig" +--- a/Makefile.kernel ++++ b/Makefile.kernel +@@ -38,9 +38,7 @@ obj-y += compat/ + + obj-$(CPTCFG_CFG80211) += net/wireless/ + obj-$(CPTCFG_MAC80211) += net/mac80211/ +-obj-$(CPTCFG_QRTR) += net/qrtr/ + obj-$(CPTCFG_QCOM_QMI_HELPERS) += drivers/soc/qcom/ +-obj-$(CPTCFG_MHI_BUS) += drivers/bus/mhi/ + obj-$(CPTCFG_WLAN) += drivers/net/wireless/ + obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/ + +--- a/drivers/net/wireless/ath/ath11k/Kconfig ++++ b/drivers/net/wireless/ath/ath11k/Kconfig +@@ -25,9 +25,9 @@ config ATH11K_PCI + tristate "Atheros ath11k PCI support" + depends on m + depends on ATH11K && PCI +- select MHI_BUS +- select QRTR +- select QRTR_MHI ++ depends on MHI_BUS ++ depends on QRTR ++ depends on QRTR_MHI + select PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL + help + This module adds support for PCIE bus +--- a/local-symbols ++++ b/local-symbols +@@ -53,14 +53,6 @@ MAC80211_MESH_PS_DEBUG= + MAC80211_TDLS_DEBUG= + MAC80211_DEBUG_COUNTERS= + MAC80211_STA_HASH_MAX_SIZE= +-QRTR= +-QRTR_SMD= +-QRTR_TUN= +-QRTR_MHI= +-MHI_BUS= +-MHI_BUS_DEBUG= +-MHI_BUS_PCI_GENERIC= +-MHI_BUS_EP= + QCOM_AOSS_QMP= + QCOM_COMMAND_DB= + QCOM_GENI_SE= diff --git a/patches/build/120-backport-fix-unaligned.h-header-location.patch b/patches/build/120-backport-fix-unaligned.h-header-location.patch new file mode 100644 index 0000000..1fe6ab2 --- /dev/null +++ b/patches/build/120-backport-fix-unaligned.h-header-location.patch @@ -0,0 +1,26 @@ +From: Shiji Yang +Date: Mon, 28 Apr 2025 22:03:18 +0800 +Subject: [PATCH] backport: fix unaligned.h header location + +unaligned.h was moved from include/asm-generic/ to include/linux/ +in 6.12-rc2 kernel. + +Link: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-6.12.y&id=5f60d5f6bbc12e782fac78110b0ee62698f3b576 +Signed-off-by: Shiji Yang +--- + backport-include/asm/unaligned.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/backport-include/asm/unaligned.h ++++ b/backport-include/asm/unaligned.h +@@ -1,6 +1,10 @@ + #ifndef __BACKPORT_ASM_GENERIC_UNALIGNED_H + #define __BACKPORT_ASM_GENERIC_UNALIGNED_H ++#if LINUX_VERSION_IS_GEQ(6,12,0) ++#include_next ++#else + #include_next ++#endif + + #if LINUX_VERSION_IS_LESS(5,7,0) + static inline u32 __get_unaligned_be24(const u8 *p) diff --git a/patches/build/140-trace_backport.patch b/patches/build/140-trace_backport.patch new file mode 100644 index 0000000..6721128 --- /dev/null +++ b/patches/build/140-trace_backport.patch @@ -0,0 +1,694 @@ +--- a/drivers/bus/mhi/host/trace.h ++++ b/drivers/bus/mhi/host/trace.h +@@ -104,7 +104,11 @@ TRACE_EVENT(mhi_gen_tre, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(name); ++#else ++ __assign_str(name, mhi_cntrl->mhi_dev->name); ++#endif + __entry->ch_num = mhi_chan->chan; + __entry->wp = mhi_tre; + __entry->tre_ptr = le64_to_cpu(mhi_tre->ptr); +@@ -132,7 +136,11 @@ TRACE_EVENT(mhi_intvec_states, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(name); ++#else ++ __assign_str(name, mhi_cntrl->mhi_dev->name); ++#endif + __entry->local_ee = mhi_cntrl->ee; + __entry->state = mhi_cntrl->dev_state; + __entry->dev_ee = dev_ee; +@@ -159,7 +167,11 @@ TRACE_EVENT(mhi_tryset_pm_state, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(name); ++#else ++ __assign_str(name, mhi_cntrl->mhi_dev->name); ++#endif + if (pm_state) + pm_state = __fls(pm_state); + __entry->pm_state = pm_state; +@@ -185,7 +197,11 @@ DECLARE_EVENT_CLASS(mhi_process_event_ri + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(name); ++#else ++ __assign_str(name, mhi_cntrl->mhi_dev->name); ++#endif + __entry->rp = rp; + __entry->ptr = le64_to_cpu(rp->ptr); + __entry->dword0 = le32_to_cpu(rp->dword[0]); +@@ -227,7 +243,11 @@ DECLARE_EVENT_CLASS(mhi_update_channel_s + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(name); ++#else ++ __assign_str(name, mhi_cntrl->mhi_dev->name); ++#endif + __entry->ch_num = mhi_chan->chan; + __entry->state = state; + __entry->reason = reason; +@@ -266,7 +286,11 @@ TRACE_EVENT(mhi_pm_st_transition, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(name); ++#else ++ __assign_str(name, mhi_cntrl->mhi_dev->name); ++#endif + __entry->state = state; + ), + +--- a/drivers/net/wireless/ath/ath10k/trace.h ++++ b/drivers/net/wireless/ath/ath10k/trace.h +@@ -55,8 +55,13 @@ DECLARE_EVENT_CLASS(ath10k_log_event, + __vstring(msg, vaf->fmt, vaf->va) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + TP_printk( +@@ -92,8 +97,13 @@ TRACE_EVENT(ath10k_log_dbg, + __vstring(msg, vaf->fmt, vaf->va) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->level = level; + __assign_vstr(msg, vaf->fmt, vaf->va); + ), +@@ -121,10 +131,17 @@ TRACE_EVENT(ath10k_log_dbg_dump, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); + __assign_str(msg); + __assign_str(prefix); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++ __assign_str(msg, msg); ++ __assign_str(prefix, prefix); ++#endif + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), +@@ -152,8 +169,13 @@ TRACE_EVENT(ath10k_wmi_cmd, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); +@@ -182,8 +204,13 @@ TRACE_EVENT(ath10k_wmi_event, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); +@@ -211,8 +238,13 @@ TRACE_EVENT(ath10k_htt_stats, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), +@@ -239,8 +271,13 @@ TRACE_EVENT(ath10k_wmi_dbglog, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->hw_type = ar->hw_rev; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); +@@ -269,8 +306,13 @@ TRACE_EVENT(ath10k_htt_pktlog, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->hw_type = ar->hw_rev; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(pktlog), buf, buf_len); +@@ -301,8 +343,13 @@ TRACE_EVENT(ath10k_htt_tx, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->msdu_id = msdu_id; + __entry->msdu_len = msdu_len; + __entry->vdev_id = vdev_id; +@@ -332,8 +379,13 @@ TRACE_EVENT(ath10k_txrx_tx_unref, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->msdu_id = msdu_id; + ), + +@@ -358,8 +410,13 @@ DECLARE_EVENT_CLASS(ath10k_hdr_event, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->len = ath10k_frm_hdr_len(data, len); + memcpy(__get_dynamic_array(data), data, __entry->len); + ), +@@ -386,8 +443,13 @@ DECLARE_EVENT_CLASS(ath10k_payload_event + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->len = len - ath10k_frm_hdr_len(data, len); + memcpy(__get_dynamic_array(payload), + data + ath10k_frm_hdr_len(data, len), __entry->len); +@@ -435,8 +497,13 @@ TRACE_EVENT(ath10k_htt_rx_desc, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->hw_type = ar->hw_rev; + __entry->len = len; + memcpy(__get_dynamic_array(rxdesc), data, len); +@@ -472,8 +539,13 @@ TRACE_EVENT(ath10k_wmi_diag_container, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->type = type; + __entry->timestamp = timestamp; + __entry->code = code; +@@ -505,8 +577,13 @@ TRACE_EVENT(ath10k_wmi_diag, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->dev)); ++ __assign_str(driver, dev_driver_string(ar->dev)); ++#endif + __entry->len = len; + memcpy(__get_dynamic_array(data), data, len); + ), +--- a/drivers/net/wireless/ath/ath11k/trace.h ++++ b/drivers/net/wireless/ath/ath11k/trace.h +@@ -48,8 +48,13 @@ TRACE_EVENT(ath11k_htt_pktlog, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + __entry->buf_len = buf_len; + __entry->pktlog_checksum = pktlog_checksum; + memcpy(__get_dynamic_array(pktlog), buf, buf_len); +@@ -77,8 +82,13 @@ TRACE_EVENT(ath11k_htt_ppdu_stats, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + __entry->len = len; + memcpy(__get_dynamic_array(ppdu), data, len); + ), +@@ -105,8 +115,13 @@ TRACE_EVENT(ath11k_htt_rxdesc, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + __entry->len = len; + __entry->log_type = log_type; + memcpy(__get_dynamic_array(rxdesc), data, len); +@@ -130,8 +145,13 @@ DECLARE_EVENT_CLASS(ath11k_log_event, + __vstring(msg, vaf->fmt, vaf->va) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + TP_printk( +@@ -171,8 +191,13 @@ TRACE_EVENT(ath11k_wmi_cmd, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++#endif + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); +@@ -201,8 +226,13 @@ TRACE_EVENT(ath11k_wmi_event, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++#endif + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); +@@ -230,8 +260,13 @@ TRACE_EVENT(ath11k_log_dbg, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++#endif + __entry->level = level; + WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), + ATH11K_MSG_MAX, vaf->fmt, +@@ -262,10 +297,17 @@ TRACE_EVENT(ath11k_log_dbg_dump, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); + __assign_str(msg); + __assign_str(prefix); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++ __assign_str(msg, msg); ++ __assign_str(prefix, prefix); ++#endif + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), +@@ -292,8 +334,13 @@ TRACE_EVENT(ath11k_wmi_diag, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++#endif + __entry->len = len; + memcpy(__get_dynamic_array(data), data, len); + ), +@@ -318,8 +365,14 @@ TRACE_EVENT(ath11k_ps_timekeeper, + __field(u32, peer_ps_timestamp) + ), + +- TP_fast_assign(__assign_str(device); ++ TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) ++ __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + memcpy(__get_dynamic_array(peer_addr), peer_addr, + ETH_ALEN); + __entry->peer_ps_state = peer_ps_state; +--- a/drivers/net/wireless/ath/ath12k/trace.h ++++ b/drivers/net/wireless/ath/ath12k/trace.h +@@ -36,8 +36,13 @@ TRACE_EVENT(ath12k_htt_pktlog, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + __entry->buf_len = buf_len; + __entry->pktlog_checksum = pktlog_checksum; + memcpy(__get_dynamic_array(pktlog), buf, buf_len); +@@ -73,8 +78,13 @@ TRACE_EVENT(ath12k_htt_ppdu_stats, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + __entry->len = len; + __entry->info = ar->pdev->timestamp.info; + __entry->sync_tstmp_lo_us = ar->pdev->timestamp.sync_timestamp_hi_us; +@@ -117,8 +127,13 @@ TRACE_EVENT(ath12k_htt_rxdesc, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ar->ab->dev)); ++ __assign_str(driver, dev_driver_string(ar->ab->dev)); ++#endif + __entry->len = len; + __entry->type = type; + __entry->info = ar->pdev->timestamp.info; +@@ -153,8 +168,13 @@ TRACE_EVENT(ath12k_wmi_diag, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, dev_name(ab->dev)); ++ __assign_str(driver, dev_driver_string(ab->dev)); ++#endif + __entry->len = len; + memcpy(__get_dynamic_array(data), data, len); + ), +--- a/drivers/net/wireless/ath/ath6kl/trace.h ++++ b/drivers/net/wireless/ath/ath6kl/trace.h +@@ -304,8 +304,13 @@ TRACE_EVENT(ath6kl_log_dbg_dump, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(msg); + __assign_str(prefix); ++#else ++ __assign_str(msg, msg); ++ __assign_str(prefix, prefix); ++#endif + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), +--- a/drivers/net/wireless/ath/trace.h ++++ b/drivers/net/wireless/ath/trace.h +@@ -44,8 +44,13 @@ TRACE_EVENT(ath_log, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(device); + __assign_str(driver); ++#else ++ __assign_str(device, wiphy_name(wiphy)); ++ __assign_str(driver, KBUILD_MODNAME); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h +@@ -41,7 +41,11 @@ TRACE_EVENT(brcmf_err, + __vstring(msg, vaf->fmt, vaf->va) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(func); ++#else ++ __assign_str(func, func); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + TP_printk("%s: %s", __get_str(func), __get_str(msg)) +@@ -57,7 +61,11 @@ TRACE_EVENT(brcmf_dbg, + ), + TP_fast_assign( + __entry->level = level; ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(func); ++#else ++ __assign_str(func, func); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + TP_printk("%s: %s", __get_str(func), __get_str(msg)) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h +@@ -81,7 +81,11 @@ TRACE_EVENT(brcms_macintstatus, + __field(u32, mask) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(dev); ++#else ++ __assign_str(dev, dev_name(dev)); ++#endif + __entry->in_isr = in_isr; + __entry->macintstatus = macintstatus; + __entry->mask = mask; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h +@@ -71,7 +71,11 @@ TRACE_EVENT(brcms_dbg, + ), + TP_fast_assign( + __entry->level = level; ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(func); ++#else ++ __assign_str(func, func); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + TP_printk("%s: %s", __get_str(func), __get_str(msg)) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h +@@ -31,7 +31,11 @@ TRACE_EVENT(brcms_txdesc, + __dynamic_array(u8, txh, txh_len) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(dev); ++#else ++ __assign_str(dev, dev_name(dev)); ++#endif + memcpy(__get_dynamic_array(txh), txh, txh_len); + ), + TP_printk("[%s] txdesc", __get_str(dev)) +@@ -54,7 +58,11 @@ TRACE_EVENT(brcms_txstatus, + __field(u16, ackphyrxsh) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(dev); ++#else ++ __assign_str(dev, dev_name(dev)); ++#endif + __entry->framelen = framelen; + __entry->frameid = frameid; + __entry->status = status; +@@ -85,7 +93,11 @@ TRACE_EVENT(brcms_ampdu_session, + __field(u16, dma_len) + ), + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(dev); ++#else ++ __assign_str(dev, dev_name(dev)); ++#endif + __entry->max_ampdu_len = max_ampdu_len; + __entry->max_ampdu_frames = max_ampdu_frames; + __entry->ampdu_len = ampdu_len; +--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h +@@ -57,7 +57,11 @@ TRACE_EVENT(iwlwifi_dbg, + ), + TP_fast_assign( + __entry->level = level; ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(function); ++#else ++ __assign_str(function, function); ++#endif + __assign_vstr(msg, vaf->fmt, vaf->va); + ), + TP_printk("%s", __get_str(msg)) +--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h +@@ -88,7 +88,11 @@ static inline void trace_ ## name(proto) + #endif + + #define DEV_ENTRY __string(dev, dev_name(dev)) ++#if LINUX_VERSION_IS_GEQ(6,10,0) + #define DEV_ASSIGN __assign_str(dev) ++#else ++#define DEV_ASSIGN __assign_str(dev, dev_name(dev)) ++#endif + + #include "iwl-devtrace-io.h" + #include "iwl-devtrace-ucode.h" +--- a/include/trace/events/qrtr.h ++++ b/include/trace/events/qrtr.h +@@ -102,7 +102,11 @@ TRACE_EVENT(qrtr_ns_message, + ), + + TP_fast_assign( ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(ctrl_pkt_str); ++#else ++ __assign_str(ctrl_pkt_str, ctrl_pkt_str); ++#endif + __entry->sq_node = sq_node; + __entry->sq_port = sq_port; + ), +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -31,9 +31,15 @@ + #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ + __field(bool, p2p) \ + __string(vif_name, sdata->name) ++#if LINUX_VERSION_IS_GEQ(6,10,0) + #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ + __entry->p2p = sdata->vif.p2p; \ + __assign_str(vif_name) ++#else ++#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ ++ __entry->p2p = sdata->vif.p2p; \ ++ __assign_str(vif_name, sdata->name) ++#endif + #define VIF_PR_FMT " vif:%s(%d%s)" + #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" + +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -446,7 +446,11 @@ TRACE_EVENT(rdev_add_virtual_intf, + ), + TP_fast_assign( + WIPHY_ASSIGN; ++#if LINUX_VERSION_IS_GEQ(6,10,0) + __assign_str(vir_intf_name); ++#else ++ __assign_str(vir_intf_name, name ? name : ""); ++#endif + __entry->type = type; + ), + TP_printk(WIPHY_PR_FMT ", virtual intf name: %s, type: %d", diff --git a/patches/build/150-ath_iommu_paging_domain_revert.patch b/patches/build/150-ath_iommu_paging_domain_revert.patch new file mode 100644 index 0000000..c296c34 --- /dev/null +++ b/patches/build/150-ath_iommu_paging_domain_revert.patch @@ -0,0 +1,32 @@ +--- a/drivers/net/wireless/ath/ath10k/snoc.c ++++ b/drivers/net/wireless/ath/ath10k/snoc.c +@@ -1638,10 +1638,10 @@ static int ath10k_fw_init(struct ath10k + + ar_snoc->fw.dev = &pdev->dev; + +- iommu_dom = iommu_paging_domain_alloc(ar_snoc->fw.dev); +- if (IS_ERR(iommu_dom)) { ++ iommu_dom = iommu_domain_alloc(&platform_bus_type); ++ if (!iommu_dom) { + ath10k_err(ar, "failed to allocate iommu domain\n"); +- ret = PTR_ERR(iommu_dom); ++ ret = -ENOMEM; + goto err_unregister; + } + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1031,10 +1031,10 @@ static int ath11k_ahb_fw_resources_init( + + ab_ahb->fw.dev = &pdev->dev; + +- iommu_dom = iommu_paging_domain_alloc(ab_ahb->fw.dev); +- if (IS_ERR(iommu_dom)) { ++ iommu_dom = iommu_domain_alloc(&platform_bus_type); ++ if (!iommu_dom) { + ath11k_err(ab, "failed to allocate iommu domain\n"); +- ret = PTR_ERR(iommu_dom); ++ ret = -ENOMEM; + goto err_unregister; + } + diff --git a/patches/build/200-iwlwifi_thermal_backport.patch b/patches/build/200-iwlwifi_thermal_backport.patch new file mode 100644 index 0000000..4180682 --- /dev/null +++ b/patches/build/200-iwlwifi_thermal_backport.patch @@ -0,0 +1,40 @@ +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +@@ -626,8 +626,13 @@ static int iwl_mvm_tzone_get_temp(struct + return 0; + } + ++#if LINUX_VERSION_IS_GEQ(6,11,0) + static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, + const struct thermal_trip *trip, int temp) ++#else ++static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, ++ int trip, int temp) ++#endif + { + struct iwl_mvm *mvm = thermal_zone_device_priv(device); + +@@ -670,13 +675,23 @@ static void iwl_mvm_thermal_zone_registe + for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) { + mvm->tz_device.trips[i].temperature = THERMAL_TEMP_INVALID; + mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE; ++#if LINUX_VERSION_IS_GEQ(6,9,0) + mvm->tz_device.trips[i].flags = THERMAL_TRIP_FLAG_RW_TEMP; ++#endif + } ++#if LINUX_VERSION_IS_GEQ(6,9,0) + mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name, + mvm->tz_device.trips, + IWL_MAX_DTS_TRIPS, + mvm, &tzone_ops, + NULL, 0, 0); ++#else ++ mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name, ++ mvm->tz_device.trips, ++ IWL_MAX_DTS_TRIPS, 0, ++ mvm, &tzone_ops, ++ NULL, 0, 0); ++#endif + if (IS_ERR(mvm->tz_device.tzone)) { + IWL_DEBUG_TEMP(mvm, + "Failed to register to thermal zone (err = %ld)\n", diff --git a/patches/build/210-wireless_netns_local_backport.patch b/patches/build/210-wireless_netns_local_backport.patch new file mode 100644 index 0000000..9e027fe --- /dev/null +++ b/patches/build/210-wireless_netns_local_backport.patch @@ -0,0 +1,55 @@ +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -162,11 +162,19 @@ int cfg80211_switch_netns(struct cfg8021 + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + if (!wdev->netdev) + continue; +- wdev->netdev->netns_immutable = false; ++#if LINUX_VERSION_IS_GEQ(6,15,0) ++ wdev->netdev->netns_immutable = true; ++#elif LINUX_VERSION_IS_GEQ(6,12,0) ++ wdev->netdev->netns_local = true; ++#endif + err = dev_change_net_namespace(wdev->netdev, net, "wlan%d"); + if (err) + break; ++#if LINUX_VERSION_IS_GEQ(6,15,0) + wdev->netdev->netns_immutable = true; ++#elif LINUX_VERSION_IS_GEQ(6,12,0) ++ wdev->netdev->netns_local = true; ++#endif + } + + if (err) { +@@ -178,11 +186,19 @@ int cfg80211_switch_netns(struct cfg8021 + list) { + if (!wdev->netdev) + continue; ++#if LINUX_VERSION_IS_GEQ(6,15,0) + wdev->netdev->netns_immutable = false; ++#elif LINUX_VERSION_IS_GEQ(6,12,0) ++ wdev->netdev->netns_local = false; ++#endif + err = dev_change_net_namespace(wdev->netdev, net, + "wlan%d"); + WARN_ON(err); ++#if LINUX_VERSION_IS_GEQ(6,15,0) + wdev->netdev->netns_immutable = true; ++#elif LINUX_VERSION_IS_GEQ(6,12,0) ++ wdev->netdev->netns_local = true; ++#endif + } + + return err; +@@ -1521,7 +1537,11 @@ static int cfg80211_netdev_notifier_call + SET_NETDEV_DEVTYPE(dev, &wiphy_type); + wdev->netdev = dev; + /* can only change netns with wiphy */ ++#if LINUX_VERSION_IS_GEQ(6,15,0) + dev->netns_immutable = true; ++#elif LINUX_VERSION_IS_GEQ(6,12,0) ++ dev->netns_local = true; ++#endif + + cfg80211_init_wdev(wdev); + break; diff --git a/patches/build/220-brcmfmac_usb_driver_backport.patch b/patches/build/220-brcmfmac_usb_driver_backport.patch new file mode 100644 index 0000000..1453bda --- /dev/null +++ b/patches/build/220-brcmfmac_usb_driver_backport.patch @@ -0,0 +1,14 @@ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1588,7 +1588,11 @@ static int brcmf_usb_reset_device(struct + + void brcmf_usb_exit(void) + { ++#if LINUX_VERSION_IS_GEQ(6,8,0) + struct device_driver *drv = &brcmf_usbdrvr.driver; ++#else ++ struct device_driver *drv = &brcmf_usbdrvr.drvwrap.driver; ++#endif + int ret; + + brcmf_dbg(USB, "Enter\n"); diff --git a/patches/build/230-fix-init_vqs-build-error-on-kernel-6.6.patch b/patches/build/230-fix-init_vqs-build-error-on-kernel-6.6.patch new file mode 100644 index 0000000..ea6461d --- /dev/null +++ b/patches/build/230-fix-init_vqs-build-error-on-kernel-6.6.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -6672,6 +6672,7 @@ static void hwsim_virtio_rx_done(struct + + static int init_vqs(struct virtio_device *vdev) + { ++#if LINUX_VERSION_IS_GEQ(6,11,0) + struct virtqueue_info vqs_info[HWSIM_NUM_VQS] = { + [HWSIM_VQ_TX] = { "tx", hwsim_virtio_tx_done }, + [HWSIM_VQ_RX] = { "rx", hwsim_virtio_rx_done }, +@@ -6679,6 +6680,19 @@ static int init_vqs(struct virtio_device + + return virtio_find_vqs(vdev, HWSIM_NUM_VQS, + hwsim_vqs, vqs_info, NULL); ++#else /* Using the old ABI, copied from kernel 6.6 */ ++ vq_callback_t *callbacks[HWSIM_NUM_VQS] = { ++ [HWSIM_VQ_TX] = hwsim_virtio_tx_done, ++ [HWSIM_VQ_RX] = hwsim_virtio_rx_done, ++ }; ++ const char *names[HWSIM_NUM_VQS] = { ++ [HWSIM_VQ_TX] = "tx", ++ [HWSIM_VQ_RX] = "rx", ++ }; ++ ++ return virtio_find_vqs(vdev, HWSIM_NUM_VQS, ++ hwsim_vqs, callbacks, names, NULL); ++#endif + } + + static int fill_vq(struct virtqueue *vq) diff --git a/patches/build/240-realtek-rtw88-BH-workqueue.patch b/patches/build/240-realtek-rtw88-BH-workqueue.patch new file mode 100644 index 0000000..5363185 --- /dev/null +++ b/patches/build/240-realtek-rtw88-BH-workqueue.patch @@ -0,0 +1,14 @@ +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -965,7 +965,11 @@ static int rtw_usb_init_rx(struct rtw_de + struct sk_buff *rx_skb; + int i; + ++#if LINUX_VERSION_IS_GEQ(6,9,0) + rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0); ++#else ++ rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq"); ++#endif + if (!rtwusb->rxwq) { + rtw_err(rtwdev, "failed to create RX work queue\n"); + return -ENOMEM; diff --git a/patches/build/300-backports-handle-genlmsg_multicast_allns-upstream-ba.patch b/patches/build/300-backports-handle-genlmsg_multicast_allns-upstream-ba.patch new file mode 100644 index 0000000..1e1b035 --- /dev/null +++ b/patches/build/300-backports-handle-genlmsg_multicast_allns-upstream-ba.patch @@ -0,0 +1,121 @@ +From 8dc94a59cfad70ec3a808add56718255eee39ab2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 29 Mar 2025 12:50:55 +0100 +Subject: [PATCH] backports: handle genlmsg_multicast_allns upstream backport + changes + +Better handle genlmsg_multicast_allns upstream backport changes that +dropped a flag to the function middle version. Use a backport function +if backports project is tried to be built on older kernel version. + +Signed-off-by: Christian Marangi +--- + backport-include/net/genetlink.h | 11 +++++ + compat/Makefile | 3 +- + compat/backport-genetlink.c | 60 +++++++++++++++++++++++ + 3 files changed, 73 insertions(+), 1 deletion(-) + +--- a/backport-include/net/genetlink.h ++++ b/backport-include/net/genetlink.h +@@ -192,4 +192,15 @@ int backport_genlmsg_multicast_allns(con + #define genlmsg_multicast_allns LINUX_BACKPORT(genlmsg_multicast_allns) + #endif /* LINUX_VERSION_IS_LESS(5,2,0) */ + ++#if LINUX_VERSION_IN_RANGE(5,15,0,5,15,169) || \ ++ LINUX_VERSION_IN_RANGE(6,1,0,6,1,115) || \ ++ LINUX_VERSION_IN_RANGE(6,6,0,6,6,58) ++#define genlmsg_multicast_allns LINUX_BACKPORT(genlmsg_multicast_allns) ++int backport_genlmsg_multicast_allns(const struct genl_family *family, ++ struct sk_buff *skb, u32 portid, ++ unsigned int group); ++#endif /* LINUX_VERSION_IN_RANGE(5,15,0,5,15,169) || ++ LINUX_VERSION_IN_RANGE(6,1,0,6,1,115) || ++ LINUX_VERSION_IN_RANGE(6,6,0,6,6,58) */ ++ + #endif /* __BACKPORT_NET_GENETLINK_H */ +--- a/compat/Makefile ++++ b/compat/Makefile +@@ -16,7 +16,8 @@ compat-$(CPTCFG_KERNEL_5_9) += backport- + compat-$(CPTCFG_KERNEL_5_10) += backport-5.10.o + compat-$(CPTCFG_KERNEL_5_11) += backport-5.11.o + compat-$(CPTCFG_KERNEL_5_13) += backport-5.13.o +-compat-$(CPTCFG_KERNEL_5_15) += backport-5.15.o ++compat-$(CPTCFG_KERNEL_5_15) += backport-5.15.o backport-genetlink.o ++compat-$(CPTCFG_KERNEL_6_1) += backport-genetlink.o + compat-$(CPTCFG_KERNEL_6_4) += backport-6.4.o + compat-$(CPTCFG_KERNEL_6_11) += backport-6.11.o + +--- a/compat/backport-genetlink.c ++++ b/compat/backport-genetlink.c +@@ -17,6 +17,7 @@ + #include + #include + ++#if LINUX_VERSION_IS_LESS(5,2,0) + static const struct genl_family *find_family_real_ops(const struct genl_ops **ops) + { + const struct genl_family *family; +@@ -249,3 +250,63 @@ int backport_genlmsg_multicast_allns(con + return genlmsg_mcast(skb, portid, group); + } + EXPORT_SYMBOL_GPL(backport_genlmsg_multicast_allns); ++#endif /* LINUX_VERSION_IS_LESS(5,2,0) */ ++ ++#if LINUX_VERSION_IN_RANGE(5,15,0,5,15,169) || \ ++ LINUX_VERSION_IN_RANGE(6,1,0,6,1,115) || \ ++ LINUX_VERSION_IN_RANGE(6,6,0,6,6,58) ++static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group) ++{ ++ struct sk_buff *tmp; ++ struct net *net, *prev = NULL; ++ bool delivered = false; ++ int err; ++ ++ rcu_read_lock(); ++ for_each_net_rcu(net) { ++ if (prev) { ++ tmp = skb_clone(skb, GFP_ATOMIC); ++ if (!tmp) { ++ err = -ENOMEM; ++ goto error; ++ } ++ err = nlmsg_multicast(prev->genl_sock, tmp, ++ portid, group, GFP_ATOMIC); ++ if (!err) ++ delivered = true; ++ else if (err != -ESRCH) ++ goto error; ++ } ++ ++ prev = net; ++ } ++ err = nlmsg_multicast(prev->genl_sock, skb, portid, group, GFP_ATOMIC); ++ ++ rcu_read_unlock(); ++ ++ if (!err) ++ delivered = true; ++ else if (err != -ESRCH) ++ return err; ++ return delivered ? 0 : -ESRCH; ++ error: ++ rcu_read_unlock(); ++ ++ kfree_skb(skb); ++ return err; ++} ++ ++int backport_genlmsg_multicast_allns(const struct genl_family *family, ++ struct sk_buff *skb, u32 portid, ++ unsigned int group) ++{ ++ if (WARN_ON_ONCE(group >= family->n_mcgrps)) ++ return -EINVAL; ++ ++ group = family->mcgrp_offset + group; ++ return genlmsg_mcast(skb, portid, group); ++} ++EXPORT_SYMBOL_GPL(backport_genlmsg_multicast_allns); ++#endif /* LINUX_VERSION_IN_RANGE(5,15,0,5,15,169) || ++ LINUX_VERSION_IN_RANGE(6,1,0,6,1,115) || ++ LINUX_VERSION_IN_RANGE(6,6,0,6,6,58) */ diff --git a/patches/build/360-change-read_new-to-read.patch b/patches/build/360-change-read_new-to-read.patch new file mode 100644 index 0000000..6387a89 --- /dev/null +++ b/patches/build/360-change-read_new-to-read.patch @@ -0,0 +1,20 @@ +--- a/drivers/net/wireless/ti/wlcore/sysfs.c ++++ b/drivers/net/wireless/ti/wlcore/sysfs.c +@@ -88,7 +88,7 @@ static ssize_t hw_pg_ver_show(struct dev + static DEVICE_ATTR_RO(hw_pg_ver); + + static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj, +- const struct bin_attribute *bin_attr, ++ struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) + { + struct device *dev = kobj_to_dev(kobj); +@@ -121,7 +121,7 @@ static ssize_t wl1271_sysfs_read_fwlog(s + + static const struct bin_attribute fwlog_attr = { + .attr = { .name = "fwlog", .mode = 0400 }, +- .read_new = wl1271_sysfs_read_fwlog, ++ .read = wl1271_sysfs_read_fwlog, + }; + + int wlcore_sysfs_init(struct wl1271 *wl) diff --git a/patches/build/400-restore-old-debugfs_fops.patch b/patches/build/400-restore-old-debugfs_fops.patch new file mode 100644 index 0000000..14a707b --- /dev/null +++ b/patches/build/400-restore-old-debugfs_fops.patch @@ -0,0 +1,252 @@ +--- a/drivers/net/wireless/ath/carl9170/debug.c ++++ b/drivers/net/wireless/ath/carl9170/debug.c +@@ -54,6 +54,7 @@ struct carl9170_debugfs_fops { + char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize, + ssize_t *len); + ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size); ++ const struct file_operations fops; + + enum carl9170_device_state req_dev_state; + }; +@@ -61,7 +62,7 @@ struct carl9170_debugfs_fops { + static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) + { +- const struct carl9170_debugfs_fops *dfops; ++ struct carl9170_debugfs_fops *dfops; + struct ar9170 *ar; + char *buf = NULL, *res_buf = NULL; + ssize_t ret = 0; +@@ -74,7 +75,8 @@ static ssize_t carl9170_debugfs_read(str + + if (!ar) + return -ENODEV; +- dfops = debugfs_get_aux(file); ++ dfops = container_of(debugfs_real_fops(file), ++ struct carl9170_debugfs_fops, fops); + + if (!dfops->read) + return -ENOSYS; +@@ -111,7 +113,7 @@ out_free: + static ssize_t carl9170_debugfs_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) + { +- const struct carl9170_debugfs_fops *dfops; ++ struct carl9170_debugfs_fops *dfops; + struct ar9170 *ar; + char *buf = NULL; + int err = 0; +@@ -126,7 +128,8 @@ static ssize_t carl9170_debugfs_write(st + + if (!ar) + return -ENODEV; +- dfops = debugfs_get_aux(file); ++ dfops = container_of(debugfs_real_fops(file), ++ struct carl9170_debugfs_fops, fops); + + if (!dfops->write) + return -ENOSYS; +@@ -162,11 +165,6 @@ out_free: + return err; + } + +-static struct debugfs_short_fops debugfs_fops = { +- .read = carl9170_debugfs_read, +- .write = carl9170_debugfs_write, +-}; +- + #define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \ + _attr, _dstate) \ + static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\ +@@ -175,6 +173,12 @@ static const struct carl9170_debugfs_fop + .write = _write, \ + .attr = _attr, \ + .req_dev_state = _dstate, \ ++ .fops = { \ ++ .open = simple_open, \ ++ .read = carl9170_debugfs_read, \ ++ .write = carl9170_debugfs_write, \ ++ .owner = THIS_MODULE \ ++ }, \ + } + + #define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \ +@@ -812,9 +816,9 @@ void carl9170_debugfs_register(struct ar + ar->hw->wiphy->debugfsdir); + + #define DEBUGFS_ADD(name) \ +- debugfs_create_file_aux(#name, carl_debugfs_##name ##_ops.attr, \ +- ar->debug_dir, ar, &carl_debugfs_##name ## _ops, \ +- &debugfs_fops) ++ debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \ ++ ar->debug_dir, ar, \ ++ &carl_debugfs_##name ## _ops.fops) + + DEBUGFS_ADD(usb_tx_anch_urbs); + DEBUGFS_ADD(usb_rx_pool_urbs); +--- a/drivers/net/wireless/broadcom/b43/debugfs.c ++++ b/drivers/net/wireless/broadcom/b43/debugfs.c +@@ -30,6 +30,7 @@ static struct dentry *rootdir; + struct b43_debugfs_fops { + ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize); + int (*write)(struct b43_wldev *dev, const char *buf, size_t count); ++ struct file_operations fops; + /* Offset of struct b43_dfs_file in struct b43_dfsentry */ + size_t file_struct_offset; + }; +@@ -490,7 +491,7 @@ static ssize_t b43_debugfs_read(struct f + size_t count, loff_t *ppos) + { + struct b43_wldev *dev; +- const struct b43_debugfs_fops *dfops; ++ struct b43_debugfs_fops *dfops; + struct b43_dfs_file *dfile; + ssize_t ret; + char *buf; +@@ -510,7 +511,8 @@ static ssize_t b43_debugfs_read(struct f + goto out_unlock; + } + +- dfops = debugfs_get_aux(file); ++ dfops = container_of(debugfs_real_fops(file), ++ struct b43_debugfs_fops, fops); + if (!dfops->read) { + err = -ENOSYS; + goto out_unlock; +@@ -553,7 +555,7 @@ static ssize_t b43_debugfs_write(struct + size_t count, loff_t *ppos) + { + struct b43_wldev *dev; +- const struct b43_debugfs_fops *dfops; ++ struct b43_debugfs_fops *dfops; + char *buf; + int err = 0; + +@@ -571,7 +573,8 @@ static ssize_t b43_debugfs_write(struct + goto out_unlock; + } + +- dfops = debugfs_get_aux(file); ++ dfops = container_of(debugfs_real_fops(file), ++ struct b43_debugfs_fops, fops); + if (!dfops->write) { + err = -ENOSYS; + goto out_unlock; +@@ -599,16 +602,16 @@ out_unlock: + } + + +-static struct debugfs_short_fops debugfs_ops = { +- .read = b43_debugfs_read, +- .write = b43_debugfs_write, +- .llseek = generic_file_llseek, +-}; +- + #define B43_DEBUGFS_FOPS(name, _read, _write) \ + static struct b43_debugfs_fops fops_##name = { \ + .read = _read, \ + .write = _write, \ ++ .fops = { \ ++ .open = simple_open, \ ++ .read = b43_debugfs_read, \ ++ .write = b43_debugfs_write, \ ++ .llseek = generic_file_llseek, \ ++ }, \ + .file_struct_offset = offsetof(struct b43_dfsentry, \ + file_##name), \ + } +@@ -700,9 +703,9 @@ void b43_debugfs_add_device(struct b43_w + + #define ADD_FILE(name, mode) \ + do { \ +- debugfs_create_file_aux(__stringify(name), \ ++ debugfs_create_file(__stringify(name), \ + mode, e->subdir, dev, \ +- &fops_##name, &debugfs_ops); \ ++ &fops_##name.fops); \ + } while (0) + + +--- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c ++++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c +@@ -31,6 +31,7 @@ static struct dentry *rootdir; + struct b43legacy_debugfs_fops { + ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize); + int (*write)(struct b43legacy_wldev *dev, const char *buf, size_t count); ++ struct file_operations fops; + /* Offset of struct b43legacy_dfs_file in struct b43legacy_dfsentry */ + size_t file_struct_offset; + /* Take wl->irq_lock before calling read/write? */ +@@ -187,7 +188,7 @@ static ssize_t b43legacy_debugfs_read(st + size_t count, loff_t *ppos) + { + struct b43legacy_wldev *dev; +- const struct b43legacy_debugfs_fops *dfops; ++ struct b43legacy_debugfs_fops *dfops; + struct b43legacy_dfs_file *dfile; + ssize_t ret; + char *buf; +@@ -207,7 +208,8 @@ static ssize_t b43legacy_debugfs_read(st + goto out_unlock; + } + +- dfops = debugfs_get_aux(file); ++ dfops = container_of(debugfs_real_fops(file), ++ struct b43legacy_debugfs_fops, fops); + if (!dfops->read) { + err = -ENOSYS; + goto out_unlock; +@@ -255,7 +257,7 @@ static ssize_t b43legacy_debugfs_write(s + size_t count, loff_t *ppos) + { + struct b43legacy_wldev *dev; +- const struct b43legacy_debugfs_fops *dfops; ++ struct b43legacy_debugfs_fops *dfops; + char *buf; + int err = 0; + +@@ -273,7 +275,8 @@ static ssize_t b43legacy_debugfs_write(s + goto out_unlock; + } + +- dfops = debugfs_get_aux(file); ++ dfops = container_of(debugfs_real_fops(file), ++ struct b43legacy_debugfs_fops, fops); + if (!dfops->write) { + err = -ENOSYS; + goto out_unlock; +@@ -305,16 +308,17 @@ out_unlock: + return err ? err : count; + } + +-static struct debugfs_short_fops debugfs_ops = { +- .read = b43legacy_debugfs_read, +- .write = b43legacy_debugfs_write, +- .llseek = generic_file_llseek +-}; + + #define B43legacy_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \ + static struct b43legacy_debugfs_fops fops_##name = { \ + .read = _read, \ + .write = _write, \ ++ .fops = { \ ++ .open = simple_open, \ ++ .read = b43legacy_debugfs_read, \ ++ .write = b43legacy_debugfs_write, \ ++ .llseek = generic_file_llseek, \ ++ }, \ + .file_struct_offset = offsetof(struct b43legacy_dfsentry, \ + file_##name), \ + .take_irqlock = _take_irqlock, \ +@@ -382,9 +386,9 @@ void b43legacy_debugfs_add_device(struct + + #define ADD_FILE(name, mode) \ + do { \ +- debugfs_create_file_aux(__stringify(name), mode, \ ++ debugfs_create_file(__stringify(name), mode, \ + e->subdir, dev, \ +- &fops_##name, &debugfs_ops); \ ++ &fops_##name.fops); \ + } while (0) + + diff --git a/patches/build/410-mac80211-convert-short-fops-to-debugfs-files.patch b/patches/build/410-mac80211-convert-short-fops-to-debugfs-files.patch new file mode 100644 index 0000000..838f0ff --- /dev/null +++ b/patches/build/410-mac80211-convert-short-fops-to-debugfs-files.patch @@ -0,0 +1,210 @@ +--- a/net/mac80211/debugfs.c ++++ b/net/mac80211/debugfs.c +@@ -42,8 +42,9 @@ static ssize_t name## _read(struct file + } + + #define DEBUGFS_READONLY_FILE_OPS(name) \ +-static const struct debugfs_short_fops name## _ops = { \ ++static const struct file_operations name## _ops = { \ + .read = name## _read, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + }; + +@@ -141,9 +142,10 @@ static ssize_t aqm_write(struct file *fi + return -EINVAL; + } + +-static const struct debugfs_short_fops aqm_ops = { ++static const struct file_operations aqm_ops = { + .write = aqm_write, + .read = aqm_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + +@@ -192,9 +194,10 @@ static ssize_t airtime_flags_write(struc + return count; + } + +-static const struct debugfs_short_fops airtime_flags_ops = { ++static const struct file_operations airtime_flags_ops = { + .write = airtime_flags_write, + .read = airtime_flags_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + +@@ -222,8 +225,9 @@ static ssize_t aql_pending_read(struct f + buf, len); + } + +-static const struct debugfs_short_fops aql_pending_ops = { ++static const struct file_operations aql_pending_ops = { + .read = aql_pending_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + +@@ -301,9 +305,10 @@ static ssize_t aql_txq_limit_write(struc + return count; + } + +-static const struct debugfs_short_fops aql_txq_limit_ops = { ++static const struct file_operations aql_txq_limit_ops = { + .write = aql_txq_limit_write, + .read = aql_txq_limit_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + +@@ -350,9 +355,10 @@ static ssize_t aql_enable_write(struct f + return count; + } + +-static const struct debugfs_short_fops aql_enable_ops = { ++static const struct file_operations aql_enable_ops = { + .write = aql_enable_write, + .read = aql_enable_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + +@@ -400,9 +406,10 @@ static ssize_t force_tx_status_write(str + return count; + } + +-static const struct debugfs_short_fops force_tx_status_ops = { ++static const struct file_operations force_tx_status_ops = { + .write = force_tx_status_write, + .read = force_tx_status_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + +@@ -427,8 +434,9 @@ static ssize_t reset_write(struct file * + return count; + } + +-static const struct debugfs_short_fops reset_ops = { ++static const struct file_operations reset_ops = { + .write = reset_write, ++ .open = simple_open, + .llseek = noop_llseek, + }; + #endif +@@ -656,8 +664,9 @@ static ssize_t stats_ ##name## _read(str + print_devstats_##name); \ + } \ + \ +-static const struct debugfs_short_fops stats_ ##name## _ops = { \ ++static const struct file_operations stats_ ##name## _ops = { \ + .read = stats_ ##name## _read, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + }; + +--- a/net/mac80211/debugfs_key.c ++++ b/net/mac80211/debugfs_key.c +@@ -26,15 +26,17 @@ static ssize_t key_##name##_read(struct + #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") + + #define KEY_OPS(name) \ +-static const struct debugfs_short_fops key_ ##name## _ops = { \ ++static const struct file_operations key_ ##name## _ops = { \ + .read = key_##name##_read, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + + #define KEY_OPS_W(name) \ +-static const struct debugfs_short_fops key_ ##name## _ops = { \ ++static const struct file_operations key_ ##name## _ops = { \ + .read = key_##name##_read, \ + .write = key_##name##_write, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + +@@ -47,8 +49,9 @@ static const struct debugfs_short_fops k + #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n") + + #define KEY_CONF_OPS(name) \ +-static const struct debugfs_short_fops key_ ##name## _ops = { \ ++static const struct file_operations key_ ##name## _ops = { \ + .read = key_conf_##name##_read, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -221,9 +221,10 @@ static ssize_t ieee80211_if_fmt_##name( + } + + #define _IEEE80211_IF_FILE_OPS(name, _read, _write) \ +-static const struct debugfs_short_fops name##_ops = { \ ++static const struct file_operations name##_ops = { \ + .read = (_read), \ + .write = (_write), \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + +--- a/net/mac80211/debugfs_sta.c ++++ b/net/mac80211/debugfs_sta.c +@@ -30,15 +30,17 @@ static ssize_t sta_ ##name## _read(struc + #define STA_READ_D(name, field) STA_READ(name, field, "%d\n") + + #define STA_OPS(name) \ +-static const struct debugfs_short_fops sta_ ##name## _ops = { \ ++static const struct file_operations sta_ ##name## _ops = { \ + .read = sta_##name##_read, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + + #define STA_OPS_RW(name) \ +-static const struct debugfs_short_fops sta_ ##name## _ops = { \ ++static const struct file_operations sta_ ##name## _ops = { \ + .read = sta_##name##_read, \ + .write = sta_##name##_write, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + +@@ -442,8 +444,9 @@ STA_OPS_RW(agg_status); + + /* link sta attributes */ + #define LINK_STA_OPS(name) \ +-static const struct debugfs_short_fops link_sta_ ##name## _ops = { \ ++static const struct file_operations link_sta_ ##name## _ops = { \ + .read = link_sta_##name##_read, \ ++ .open = simple_open, \ + .llseek = generic_file_llseek, \ + } + +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -249,8 +249,9 @@ static ssize_t rcname_read(struct file * + ref->ops->name, len); + } + +-const struct debugfs_short_fops rcname_ops = { ++const struct file_operations rcname_ops = { + .read = rcname_read, ++ .open = simple_open, + .llseek = default_llseek, + }; + #endif +--- a/net/mac80211/rate.h ++++ b/net/mac80211/rate.h +@@ -62,7 +62,7 @@ static inline void rate_control_add_sta_ + #endif + } + +-extern const struct debugfs_short_fops rcname_ops; ++extern const struct file_operations rcname_ops; + + static inline void rate_control_add_debugfs(struct ieee80211_local *local) + { diff --git a/patches/mt7601u/001-wifi-mt7601u-update-firmware-path.patch b/patches/mt7601u/001-wifi-mt7601u-update-firmware-path.patch new file mode 100644 index 0000000..5d98290 --- /dev/null +++ b/patches/mt7601u/001-wifi-mt7601u-update-firmware-path.patch @@ -0,0 +1,55 @@ +From patchwork Mon May 15 22:56:53 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13242309 +X-Patchwork-Delegate: kvalo@adurom.com +Return-Path: +Date: Tue, 16 May 2023 00:56:53 +0200 +From: Daniel Golle +To: Jakub Kicinski , Kalle Valo , + "David S. Miller" , + Eric Dumazet , + Paolo Abeni , + Matthias Brugger , + AngeloGioacchino Del Regno + , + linux-wireless@vger.kernel.org, netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org +Subject: [PATCH] wifi: mt7601u: update firmware path +Message-ID: + +MIME-Version: 1.0 +Content-Disposition: inline +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless@vger.kernel.org + +mt7601u.bin was moved to mediatek/ folder in linux-wireless via commit +8451c2b1 ("mt76xx: Move the old Mediatek WiFi firmware to mediatek") +and linux-firmware release 20230515. + +Update the firmware path requested by the mt7601u driver to follow up +with the move of the file. + +Signed-off-by: Daniel Golle +--- + drivers/net/wireless/mediatek/mt7601u/usb.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + + +base-commit: 0d9b41daa5907756a31772d8af8ac5ff25cf17c1 + +--- a/drivers/net/wireless/mediatek/mt7601u/usb.h ++++ b/drivers/net/wireless/mediatek/mt7601u/usb.h +@@ -8,7 +8,7 @@ + + #include "mt7601u.h" + +-#define MT7601U_FIRMWARE "mt7601u.bin" ++#define MT7601U_FIRMWARE "mediatek/mt7601u.bin" + + #define MT_VEND_REQ_MAX_RETRY 10 + #define MT_VEND_REQ_TOUT_MS 300 diff --git a/patches/mt7601u/100-w1fi-mt7601u-Add-AP-mode-support.patch b/patches/mt7601u/100-w1fi-mt7601u-Add-AP-mode-support.patch new file mode 100644 index 0000000..654954e --- /dev/null +++ b/patches/mt7601u/100-w1fi-mt7601u-Add-AP-mode-support.patch @@ -0,0 +1,36 @@ +From: Chukun Pan +To: Jakub Kicinski +Cc: Kalle Valo , + "David S . Miller" , + Eric Dumazet , + Paolo Abeni , + Matthias Brugger , + Lintel Huang , + linux-wireless@vger.kernel.org, netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, Chukun Pan +Subject: [PATCH] wifi: mt7601u: Add AP mode support +Date: Tue, 26 Jul 2022 00:16:03 +0800 [thread overview] +Message-ID: <20220725161603.15201-1-amadeus@jmu.edu.cn> (raw) + +Add AP mode support to mt7601u chipset. +Simply tested it with firmware version +201302052146 and it seems working fine. + +Run-tested-by: Lintel Huang +Signed-off-by: Chukun Pan +--- + drivers/net/wireless/mediatek/mt7601u/init.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/mediatek/mt7601u/init.c ++++ b/drivers/net/wireless/mediatek/mt7601u/init.c +@@ -609,7 +609,8 @@ int mt7601u_register_device(struct mt760 + SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); + + wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; +- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP); + wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; + + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); diff --git a/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch b/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch new file mode 100644 index 0000000..cfb7dcf --- /dev/null +++ b/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -5712,6 +5712,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") + MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); + + static const struct pci_device_id mwl8k_pci_id_table[] = { ++ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, diff --git a/patches/mwl/801-libertas-configure-sysfs-links.patch b/patches/mwl/801-libertas-configure-sysfs-links.patch new file mode 100644 index 0000000..4a4a9b2 --- /dev/null +++ b/patches/mwl/801-libertas-configure-sysfs-links.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/wireless/marvell/libertas/cfg.c ++++ b/drivers/net/wireless/marvell/libertas/cfg.c +@@ -2102,6 +2102,8 @@ struct wireless_dev *lbs_cfg_alloc(struc + goto err_wiphy_new; + } + ++ set_wiphy_dev(wdev->wiphy, dev); ++ + return wdev; + + err_wiphy_new: +--- a/drivers/net/wireless/marvell/libertas/main.c ++++ b/drivers/net/wireless/marvell/libertas/main.c +@@ -852,6 +852,7 @@ struct lbs_private *lbs_add_card(void *c + goto err_adapter; + } + ++ dev_net_set(dev, wiphy_net(wdev->wiphy)); + dev->ieee80211_ptr = wdev; + dev->ml_priv = priv; + SET_NETDEV_DEV(dev, dmdev); diff --git a/patches/mwl/802-libertas-set-wireless-macaddr.patch b/patches/mwl/802-libertas-set-wireless-macaddr.patch new file mode 100644 index 0000000..97ddd66 --- /dev/null +++ b/patches/mwl/802-libertas-set-wireless-macaddr.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/marvell/libertas/cfg.c ++++ b/drivers/net/wireless/marvell/libertas/cfg.c +@@ -2179,6 +2179,8 @@ int lbs_cfg_register(struct lbs_private + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + wdev->wiphy->reg_notifier = lbs_reg_notifier; + ++ memcpy(wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN); ++ + ret = wiphy_register(wdev->wiphy); + if (ret < 0) + pr_err("cannot register wiphy device\n"); diff --git a/patches/mwl/900-mwifiex-increase-the-global-limit-up-to-4-SSID.patch b/patches/mwl/900-mwifiex-increase-the-global-limit-up-to-4-SSID.patch new file mode 100644 index 0000000..484b37b --- /dev/null +++ b/patches/mwl/900-mwifiex-increase-the-global-limit-up-to-4-SSID.patch @@ -0,0 +1,41 @@ +From ef8098cd6cb8b5989afef2e8461fe6ba9570a854 Mon Sep 17 00:00:00 2001 +From: Josef Schlehofer +Date: Wed, 24 Nov 2021 12:47:40 +0100 +Subject: [PATCH] mwifiex: increase the global limit up to 4 SSID + +Firmware for SDIO (88W8997), which is used in Turris MOX SDIO addon [1], +allows up to 4 SSID. Unfortunately, driver (even in mainline kernel) +has a global limit for all Marvell cards up to 3 SSID. + +Pali Rohár tested this patch and verified that the SDIO Wi-Fi addon works +with the 4 SSID. So, let's increase the global limit from 3 to 4. + +Ideally, this patch should be done differently before sending +it to Linux kernel. It means that limit definition should be moved to +the card-specific structure. + +[1] https://docs.turris.cz/hw/mox/addons/#wi-fi-sdio +--- + drivers/net/wireless/marvell/mwifiex/decl.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/marvell/mwifiex/decl.h ++++ b/drivers/net/wireless/marvell/mwifiex/decl.h +@@ -18,7 +18,7 @@ + #include + + #define MWIFIEX_BSS_COEX_COUNT 2 +-#define MWIFIEX_MAX_BSS_NUM (3) ++#define MWIFIEX_MAX_BSS_NUM (4) + + #define MWIFIEX_DMA_ALIGN_SZ 64 + #define MWIFIEX_RX_HEADROOM 64 +@@ -123,7 +123,7 @@ + #define MWIFIEX_RATE_INDEX_OFDM0 4 + + #define MWIFIEX_MAX_STA_NUM 3 +-#define MWIFIEX_MAX_UAP_NUM 3 ++#define MWIFIEX_MAX_UAP_NUM 4 + #define MWIFIEX_MAX_P2P_NUM 3 + + #define MWIFIEX_A_BAND_START_FREQ 5000 diff --git a/patches/mwl/940-mwl8k_init_devices_synchronously.patch b/patches/mwl/940-mwl8k_init_devices_synchronously.patch new file mode 100644 index 0000000..d09cfac --- /dev/null +++ b/patches/mwl/940-mwl8k_init_devices_synchronously.patch @@ -0,0 +1,20 @@ +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -6298,6 +6298,8 @@ static int mwl8k_probe(struct pci_dev *p + + priv->running_bsses = 0; + ++ wait_for_completion(&priv->firmware_loading_complete); ++ + return rc; + + err_stop_firmware: +@@ -6331,8 +6333,6 @@ static void mwl8k_remove(struct pci_dev + return; + priv = hw->priv; + +- wait_for_completion(&priv->firmware_loading_complete); +- + if (priv->fw_state == FW_STATE_ERROR) { + mwl8k_hw_reset(priv); + goto unmap; diff --git a/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch b/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch new file mode 100644 index 0000000..fc57ff0 --- /dev/null +++ b/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch @@ -0,0 +1,177 @@ +From f7252b1b5755150535af226e806594bbefd45e0f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Sun, 26 Sep 2021 14:39:44 +0200 +Subject: [PATCH] mwifiex: Print stringified name of command in error log +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Failed hex command number in error log is hard to understand. +So add also more human readable stringified command name into error log. + +Signed-off-by: Pali Rohár +--- + drivers/net/wireless/marvell/mwifiex/cmdevt.c | 96 +++++++++++++++++-- + drivers/net/wireless/marvell/mwifiex/main.h | 2 + + .../wireless/marvell/mwifiex/sta_cmdresp.c | 5 +- + .../net/wireless/marvell/mwifiex/uap_cmd.c | 3 +- + 4 files changed, 95 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c ++++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c +@@ -16,6 +16,85 @@ + + static void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); + ++const char * ++mwifiex_cmd_to_str(u16 command) ++{ ++ switch (command) { ++ case HostCmd_CMD_GET_HW_SPEC: return "GET_HW_SPEC"; ++ case HostCmd_CMD_802_11_SCAN: return "SCAN"; ++ case HostCmd_CMD_802_11_GET_LOG: return "GET_LOG"; ++ case HostCmd_CMD_MAC_MULTICAST_ADR: return "MAC_MULTICAST_ADR"; ++ case HostCmd_CMD_802_11_EEPROM_ACCESS: return "EEPROM_ACCESS"; ++ case HostCmd_CMD_802_11_ASSOCIATE: return "ASSOCIATE"; ++ case HostCmd_CMD_802_11_SNMP_MIB: return "SNMP_MIB"; ++ case HostCmd_CMD_MAC_REG_ACCESS: return "MAC_REG_ACCESS"; ++ case HostCmd_CMD_BBP_REG_ACCESS: return "BBP_REG_ACCESS"; ++ case HostCmd_CMD_RF_REG_ACCESS: return "RF_REG_ACCESS"; ++ case HostCmd_CMD_PMIC_REG_ACCESS: return "PMIC_REG_ACCESS"; ++ case HostCmd_CMD_RF_TX_PWR: return "RF_TX_PWR"; ++ case HostCmd_CMD_RF_ANTENNA: return "RF_ANTENNA"; ++ case HostCmd_CMD_802_11_DEAUTHENTICATE: return "DEAUTHENTICATE"; ++ case HostCmd_CMD_MAC_CONTROL: return "MAC_CONTROL"; ++ case HostCmd_CMD_802_11_AD_HOC_START: return "AD_HOC_START"; ++ case HostCmd_CMD_802_11_AD_HOC_JOIN: return "AD_HOC_JOIN"; ++ case HostCmd_CMD_802_11_AD_HOC_STOP: return "AD_HOC_STOP"; ++ case HostCmd_CMD_802_11_MAC_ADDRESS: return "MAC_ADDRESS"; ++ case HostCmd_CMD_802_11D_DOMAIN_INFO: return "DOMAIN_INFO"; ++ case HostCmd_CMD_802_11_KEY_MATERIAL: return "KEY_MATERIAL"; ++ case HostCmd_CMD_802_11_BG_SCAN_CONFIG: return "BG_SCAN_CONFIG"; ++ case HostCmd_CMD_802_11_BG_SCAN_QUERY: return "BG_SCAN_QUERY"; ++ case HostCmd_CMD_WMM_GET_STATUS: return "WMM_GET_STATUS"; ++ case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: return "SUBSCRIBE_EVENT"; ++ case HostCmd_CMD_802_11_TX_RATE_QUERY: return "TX_RATE_QUERY"; ++ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: return "IBSS_COALESCING_STATUS"; ++ case HostCmd_CMD_MEM_ACCESS: return "MEM_ACCESS"; ++ case HostCmd_CMD_CFG_DATA: return "CFG_DATA"; ++ case HostCmd_CMD_VERSION_EXT: return "VERSION_EXT"; ++ case HostCmd_CMD_MEF_CFG: return "MEF_CFG"; ++ case HostCmd_CMD_RSSI_INFO: return "RSSI_INFO"; ++ case HostCmd_CMD_FUNC_INIT: return "FUNC_INIT"; ++ case HostCmd_CMD_FUNC_SHUTDOWN: return "FUNC_SHUTDOWN"; ++ case HOST_CMD_APCMD_SYS_RESET: return "SYS_RESET"; ++ case HostCmd_CMD_UAP_SYS_CONFIG: return "UAP_SYS_CONFIG"; ++ case HostCmd_CMD_UAP_BSS_START: return "UAP_BSS_START"; ++ case HostCmd_CMD_UAP_BSS_STOP: return "UAP_BSS_STOP"; ++ case HOST_CMD_APCMD_STA_LIST: return "STA_LIST"; ++ case HostCmd_CMD_UAP_STA_DEAUTH: return "UAP_STA_DEAUTH"; ++ case HostCmd_CMD_11N_CFG: return "11N_CFG"; ++ case HostCmd_CMD_11N_ADDBA_REQ: return "ADDBA_REQ"; ++ case HostCmd_CMD_11N_ADDBA_RSP: return "ADDBA_RSP"; ++ case HostCmd_CMD_11N_DELBA: return "DELBA"; ++ case HostCmd_CMD_RECONFIGURE_TX_BUFF: return "RECONFIGURE_TX_BUFF"; ++ case HostCmd_CMD_CHAN_REPORT_REQUEST: return "CHAN_REPORT_REQUEST"; ++ case HostCmd_CMD_AMSDU_AGGR_CTRL: return "AMSDU_AGGR_CTRL"; ++ case HostCmd_CMD_TXPWR_CFG: return "TXPWR_CFG"; ++ case HostCmd_CMD_TX_RATE_CFG: return "TX_RATE_CFG"; ++ case HostCmd_CMD_ROBUST_COEX: return "ROBUST_COEX"; ++ case HostCmd_CMD_802_11_PS_MODE_ENH: return "PS_MODE_ENH"; ++ case HostCmd_CMD_802_11_HS_CFG_ENH: return "HS_CFG_ENH"; ++ case HostCmd_CMD_P2P_MODE_CFG: return "P2P_MODE_CFG"; ++ case HostCmd_CMD_CAU_REG_ACCESS: return "CAU_REG_ACCESS"; ++ case HostCmd_CMD_SET_BSS_MODE: return "SET_BSS_MODE"; ++ case HostCmd_CMD_PCIE_DESC_DETAILS: return "PCIE_DESC_DETAILS"; ++ case HostCmd_CMD_802_11_SCAN_EXT: return "SCAN_EXT"; ++ case HostCmd_CMD_COALESCE_CFG: return "COALESCE_CFG"; ++ case HostCmd_CMD_MGMT_FRAME_REG: return "MGMT_FRAME_REG"; ++ case HostCmd_CMD_REMAIN_ON_CHAN: return "REMAIN_ON_CHAN"; ++ case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG: return "GTK_REKEY_OFFLOAD_CFG"; ++ case HostCmd_CMD_11AC_CFG: return "11AC_CFG"; ++ case HostCmd_CMD_HS_WAKEUP_REASON: return "HS_WAKEUP_REASON"; ++ case HostCmd_CMD_TDLS_CONFIG: return "TDLS_CONFIG"; ++ case HostCmd_CMD_MC_POLICY: return "MC_POLICY"; ++ case HostCmd_CMD_TDLS_OPER: return "TDLS_OPER"; ++ case HostCmd_CMD_FW_DUMP_EVENT: return "FW_DUMP_EVENT"; ++ case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: return "SDIO_SP_RX_AGGR_CFG"; ++ case HostCmd_CMD_STA_CONFIGURE: return "STA_CONFIGURE"; ++ case HostCmd_CMD_CHAN_REGION_CFG: return "CHAN_REGION_CFG"; ++ case HostCmd_CMD_PACKET_AGGR_CTRL: return "PACKET_AGGR_CTRL"; ++ default: return "UNKNOWN"; ++ } ++} ++ + /* + * This function initializes a command node. + * +@@ -191,8 +270,8 @@ static int mwifiex_dnld_cmd_to_fw(struct + cmd_code != HostCmd_CMD_FUNC_SHUTDOWN && + cmd_code != HostCmd_CMD_FUNC_INIT) { + mwifiex_dbg(adapter, ERROR, +- "DNLD_CMD: FW in reset state, ignore cmd %#x\n", +- cmd_code); ++ "DNLD_CMD: FW in reset state, ignore cmd %s (%#x)\n", ++ mwifiex_cmd_to_str(cmd_code), cmd_code); + mwifiex_recycle_cmd_node(adapter, cmd_node); + queue_work(adapter->workqueue, &adapter->main_work); + return -1; +@@ -651,8 +730,8 @@ int mwifiex_send_cmd(struct mwifiex_priv + /* Return error, since the command preparation failed */ + if (ret) { + mwifiex_dbg(adapter, ERROR, +- "PREP_CMD: cmd %#x preparation failed\n", +- cmd_no); ++ "PREP_CMD: cmd %s (%#x) preparation failed\n", ++ mwifiex_cmd_to_str(cmd_no), cmd_no); + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + return -1; + } +@@ -1262,8 +1341,8 @@ mwifiex_process_sleep_confirm_resp(struc + + if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { + mwifiex_dbg(adapter, ERROR, +- "%s: rcvd unexpected resp for cmd %#x, result = %x\n", +- __func__, command, result); ++ "%s: rcvd unexpected resp for cmd %s (%#x), result = %x\n", ++ __func__, mwifiex_cmd_to_str(command), command, result); + return; + } + +--- a/drivers/net/wireless/marvell/mwifiex/main.h ++++ b/drivers/net/wireless/marvell/mwifiex/main.h +@@ -1090,6 +1090,8 @@ void mwifiex_cancel_all_pending_cmd(stru + void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter); + void mwifiex_cancel_scan(struct mwifiex_adapter *adapter); + ++const char *mwifiex_cmd_to_str(u16 command); ++ + void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node); + +--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c ++++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +@@ -36,8 +36,9 @@ mwifiex_process_cmdresp_error(struct mwi + struct host_cmd_ds_802_11_ps_mode_enh *pm; + + mwifiex_dbg(adapter, ERROR, +- "CMD_RESP: cmd %#x error, result=%#x\n", +- resp->command, resp->result); ++ "CMD_RESP: cmd %s (%#x) error, result=%#x\n", ++ mwifiex_cmd_to_str(le16_to_cpu(resp->command)), ++ le16_to_cpu(resp->command), le16_to_cpu(resp->result)); + + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status = -1; +--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +@@ -964,7 +964,8 @@ int mwifiex_uap_prepare_cmd(struct mwifi + break; + default: + mwifiex_dbg(priv->adapter, ERROR, +- "PREP_CMD: unknown cmd %#x\n", cmd_no); ++ "PREP_CMD: unknown cmd (%s) %#x\n", ++ mwifiex_cmd_to_str(cmd_no), cmd_no); + return -1; + } + diff --git a/patches/rt2x00/100-rt2x00_options.patch b/patches/rt2x00/100-rt2x00_options.patch new file mode 100644 index 0000000..295904c --- /dev/null +++ b/patches/rt2x00/100-rt2x00_options.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -226,36 +226,37 @@ config RT2800SOC + + + config RT2800_LIB +- tristate ++ tristate "RT2800 USB/PCI support" + depends on m + + config RT2800_LIB_MMIO +- tristate ++ tristate "RT2800 MMIO support" + depends on m + select RT2X00_LIB_MMIO + select RT2800_LIB + + config RT2X00_LIB_MMIO +- tristate ++ tristate "RT2x00 MMIO support" + depends on m + + config RT2X00_LIB_PCI +- tristate ++ tristate "RT2x00 PCI support" + depends on m + select RT2X00_LIB + + config RT2X00_LIB_SOC +- tristate ++ tristate "RT2x00 SoC support" ++ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620 + depends on m + select RT2X00_LIB + + config RT2X00_LIB_USB +- tristate ++ tristate "RT2x00 USB support" + depends on m + select RT2X00_LIB + + config RT2X00_LIB +- tristate ++ tristate "RT2x00 support" + depends on m + + config RT2X00_LIB_FIRMWARE diff --git a/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch b/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch new file mode 100644 index 0000000..b4106b0 --- /dev/null +++ b/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch @@ -0,0 +1,30 @@ +From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -211,7 +211,7 @@ endif + config RT2800SOC + tristate "Ralink WiSoC support" + depends on m +- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620 ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + select RT2X00_LIB_SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO +@@ -246,7 +246,7 @@ config RT2X00_LIB_PCI + + config RT2X00_LIB_SOC + tristate "RT2x00 SoC support" +- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620 ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + depends on m + select RT2X00_LIB + diff --git a/patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch b/patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch new file mode 100644 index 0000000..1eba6a7 --- /dev/null +++ b/patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch @@ -0,0 +1,228 @@ +From 1046fc9e98936991aeb0b0656c84833d96a63c0f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 15 Oct 2023 14:22:49 +0200 +Subject: [PATCH 1/5] wifi: rt2x00: Add support for loading EEPROM from + userspace + +Add support for loading EEPROM from userspace. + +Signed-off-by: Christian Marangi +--- + drivers/net/wireless/ralink/rt2x00/Kconfig | 5 ++ + drivers/net/wireless/ralink/rt2x00/Makefile | 1 + + .../net/wireless/ralink/rt2x00/rt2800soc.c | 15 +--- + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + + .../net/wireless/ralink/rt2x00/rt2x00dev.c | 9 +++ + .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 75 +++++++++++++++++++ + .../net/wireless/ralink/rt2x00/rt2x00soc.c | 1 + + .../net/wireless/ralink/rt2x00/rt2x00soc.h | 9 +++ + 8 files changed, 102 insertions(+), 14 deletions(-) + create mode 100644 drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c + +--- a/local-symbols ++++ b/local-symbols +@@ -336,6 +336,7 @@ RT2X00_LIB_FIRMWARE= + RT2X00_LIB_CRYPTO= + RT2X00_LIB_LEDS= + RT2X00_LIB_DEBUGFS= ++RT2X00_LIB_EEPROM= + RT2X00_DEBUG= + WLAN_VENDOR_REALTEK= + RTL8180= +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -70,6 +70,7 @@ config RT2800PCI + select RT2X00_LIB_MMIO + select RT2X00_LIB_PCI + select RT2X00_LIB_FIRMWARE ++ select RT2X00_LIB_EEPROM + select RT2X00_LIB_CRYPTO + depends on CRC_CCITT + depends on EEPROM_93CX6 +@@ -216,6 +217,7 @@ config RT2800SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO + select RT2X00_LIB_FIRMWARE ++ select RT2X00_LIB_EEPROM + select RT2800_LIB + select RT2800_LIB_MMIO + help +@@ -266,6 +268,9 @@ config RT2X00_LIB_FIRMWARE + config RT2X00_LIB_CRYPTO + bool + ++config RT2X00_LIB_EEPROM ++ bool ++ + config RT2X00_LIB_LEDS + bool + default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) +--- a/drivers/net/wireless/ralink/rt2x00/Makefile ++++ b/drivers/net/wireless/ralink/rt2x00/Makefile +@@ -8,6 +8,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) + + rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o + rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o + rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o ++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o + + obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o + obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -90,19 +90,6 @@ static int rt2800soc_set_device_state(st + return retval; + } + +-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) +-{ +- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); +- +- if (!base_addr) +- return -ENOMEM; +- +- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); +- +- iounmap(base_addr); +- return 0; +-} +- + /* Firmware functions */ + static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) + { +@@ -172,7 +159,7 @@ static const struct rt2800_ops rt2800soc + .register_multiread = rt2x00mmio_register_multiread, + .register_multiwrite = rt2x00mmio_register_multiwrite, + .regbusy_read = rt2x00mmio_regbusy_read, +- .read_eeprom = rt2800soc_read_eeprom, ++ .read_eeprom = rt2x00lib_read_eeprom, + .hwcrypt_disabled = rt2800soc_hwcrypt_disabled, + .drv_write_firmware = rt2800soc_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -692,6 +692,7 @@ enum rt2x00_capability_flags { + REQUIRE_HT_TX_DESC, + REQUIRE_PS_AUTOWAKE, + REQUIRE_DELAYED_RFKILL, ++ REQUIRE_EEPROM_FILE, + + /* + * Capabilities +@@ -1504,4 +1505,13 @@ void rt2x00lib_remove_dev(struct rt2x00_ + int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev); + int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev); + ++/* ++ * EEPROM file handlers. ++ */ ++#ifdef CPTCFG_RT2X00_LIB_EEPROM ++int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev); ++#else ++#define rt2x00lib_read_eeprom NULL ++#endif /* CPTCFG_RT2X00_LIB_EEPROM */ ++ + #endif /* RT2X00_H */ +--- /dev/null ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -0,0 +1,79 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright (C) 2004 - 2009 Ivo van Doorn ++ * Copyright (C) 2004 - 2009 Gertjan van Wingerde ++ * ++ */ ++ ++/* Module: rt2x00lib ++ * Abstract: rt2x00 eeprom file loading routines. ++ */ ++ ++#include ++#include ++#include ++ ++#include "rt2x00.h" ++#include "rt2x00soc.h" ++ ++static const char * ++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) ++{ ++ struct device_node *np = rt2x00dev->dev->of_node; ++ const char *eep; ++ ++ if (np && !of_property_read_string(np, "ralink,eeprom", &eep)) ++ return eep; ++ ++ return NULL; ++} ++ ++static int rt2x00lib_read_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct firmware *ee; ++ const char *ee_name; ++ int retval; ++ ++ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev); ++ if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) { ++ rt2x00_err(rt2x00dev, "Required EEPROM name is missing."); ++ return -EINVAL; ++ } ++ ++ if (!ee_name) ++ return -ENOENT; ++ ++ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name); ++ ++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev); ++ if (retval) { ++ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n"); ++ return retval; ++ } ++ ++ if (!ee || !ee->size || !ee->data) { ++ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n"); ++ retval = -ENOENT; ++ goto err_exit; ++ } ++ ++ if (ee->size != rt2x00dev->ops->eeprom_size) { ++ rt2x00_err(rt2x00dev, ++ "EEPROM file size is invalid, it should be %d bytes\n", ++ rt2x00dev->ops->eeprom_size); ++ retval = -EINVAL; ++ goto err_release_ee; ++ } ++ ++ memcpy(rt2x00dev->eeprom, ee->data, rt2x00dev->ops->eeprom_size); ++ ++err_release_ee: ++ release_firmware(ee); ++err_exit: ++ return retval; ++} ++ ++int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev) ++{ ++ return rt2x00lib_read_eeprom_file(rt2x00dev); ++} ++EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom); +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c +@@ -86,6 +86,7 @@ int rt2x00soc_probe(struct platform_devi + if (IS_ERR(rt2x00dev->clk)) + rt2x00dev->clk = NULL; + ++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags); + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); + + retval = rt2x00soc_alloc_reg(rt2x00dev); +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -278,6 +278,9 @@ static int rt2800pci_read_eeprom(struct + { + int retval; + ++ if (!rt2x00lib_read_eeprom(rt2x00dev)) ++ return 0; ++ + if (rt2800pci_efuse_detect(rt2x00dev)) + retval = rt2800pci_read_eeprom_efuse(rt2x00dev); + else diff --git a/patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch b/patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch new file mode 100644 index 0000000..befd594 --- /dev/null +++ b/patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch @@ -0,0 +1,108 @@ +From 71261ca81b491a4c3b08690347c12e96a75ad0d0 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 00:55:04 +0100 +Subject: [PATCH 3/5] wifi: rt2x00: Add support for loading EEPROM from MTD + +Add support for loading EEPROM from MTD. + +Signed-off-by: John Crispin +Signed-off-by: Christian Marangi +--- + drivers/net/wireless/ralink/rt2x00/Kconfig | 1 + + .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 66 +++++++++++++++++++ + 2 files changed, 67 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -220,6 +220,7 @@ config RT2800SOC + select RT2X00_LIB_EEPROM + select RT2800_LIB + select RT2800_LIB_MMIO ++ select MTD if SOC_RT288X || SOC_RT305X + help + This adds support for Ralink WiSoC devices. + Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -11,10 +11,66 @@ + #include + #include + #include ++#if IS_ENABLED(CONFIG_MTD) ++#include ++#include ++#endif + + #include "rt2x00.h" + #include "rt2x00soc.h" + ++#if IS_ENABLED(CONFIG_MTD) ++static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) ++{ ++ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL; ++ int size, offset = 0; ++ struct mtd_info *mtd; ++ const char *part; ++ const __be32 *list; ++ phandle phandle; ++ size_t retlen; ++ int ret; ++ ++ list = of_get_property(np, "ralink,mtd-eeprom", &size); ++ if (!list) ++ return -ENOENT; ++ ++ phandle = be32_to_cpup(list++); ++ if (phandle) ++ mtd_np = of_find_node_by_phandle(phandle); ++ if (!mtd_np) { ++ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n"); ++ return -EINVAL; ++ } ++ ++ part = of_get_property(mtd_np, "label", NULL); ++ if (!part) ++ part = mtd_np->name; ++ ++ mtd = get_mtd_device_nm(part); ++ if (IS_ERR(mtd)) { ++ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part); ++ return PTR_ERR(mtd); ++ } ++ ++ if (size > sizeof(*list)) ++ offset = be32_to_cpup(list); ++ ++ ret = mtd_read(mtd, offset, rt2x00dev->ops->eeprom_size, ++ &retlen, (u_char *)rt2x00dev->eeprom); ++ put_mtd_device(mtd); ++ ++ if (ret || retlen != rt2x00dev->ops->eeprom_size) { ++ dev_err(rt2x00dev->dev, "failed to load eeprom from device \"%s\"\n", part); ++ return ret; ++ } ++ ++ dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part); ++ ++ return ret; ++} ++#endif ++ + static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) + { +@@ -74,6 +130,14 @@ err_exit: + + int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev) + { ++ int ret; ++ ++#if IS_ENABLED(CONFIG_MTD) ++ ret = rt2800lib_read_eeprom_mtd(rt2x00dev); ++ if (!ret) ++ return 0; ++#endif ++ + return rt2x00lib_read_eeprom_file(rt2x00dev); + } + EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom); diff --git a/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch b/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch new file mode 100644 index 0000000..960b5c0 --- /dev/null +++ b/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch @@ -0,0 +1,44 @@ +From 9c9a3c27b96e057f3c3f47151d7a170d84e3bb5f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 15 Oct 2023 15:31:47 +0200 +Subject: [PATCH 4/5] wifi: rt2x00: Support EEPROM swap binding + +Add binding "ralink,eeprom-swap" to swap bytes of EEPROM before using +it. + +Signed-off-by: Christian Marangi +--- + drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -20,6 +20,19 @@ + #include "rt2x00soc.h" + + #if IS_ENABLED(CONFIG_MTD) ++static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev) ++{ ++ struct device_node *np = rt2x00dev->dev->of_node; ++ size_t len = rt2x00dev->ops->eeprom_size; ++ int i; ++ ++ if (!of_find_property(np, "ralink,eeprom-swap", NULL)) ++ return; ++ ++ for (i = 0; i < len / sizeof(u16); i++) ++ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]); ++} ++ + static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) + { + struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL; +@@ -65,6 +78,8 @@ static int rt2800lib_read_eeprom_mtd(str + return ret; + } + ++ rt2800lib_eeprom_swap(rt2x00dev); ++ + dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part); + + return ret; diff --git a/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch b/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch new file mode 100644 index 0000000..b649890 --- /dev/null +++ b/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch @@ -0,0 +1,96 @@ +From 9008cdacdc41f8233f4444b86cf3a17201686e2d Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Tue, 18 Jul 2023 20:18:16 +0800 +Subject: [PATCH 5/5] wifi: rt2x00: support loading eeprom from NVMEM cells + +This patch allows rt2x00 to load eeprom from "eeprom" NVMEM cell. + +Example: + +/* load eeprom from NVMEM provider 'eep' */ +&wmac { + nvmem-cells = <&eep>; + nvmem-cell-names = "eeprom"; +}; + +Signed-off-by: Shiji Yang +Signed-off-by: Christian Marangi +--- + .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 41 ++++++++++++++++++- + 1 file changed, 40 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -15,11 +15,11 @@ + #include + #include + #endif ++#include + + #include "rt2x00.h" + #include "rt2x00soc.h" + +-#if IS_ENABLED(CONFIG_MTD) + static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev) + { + struct device_node *np = rt2x00dev->dev->of_node; +@@ -33,6 +33,7 @@ static void rt2800lib_eeprom_swap(struct + rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]); + } + ++#if IS_ENABLED(CONFIG_MTD) + static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) + { + struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL; +@@ -86,6 +87,40 @@ static int rt2800lib_read_eeprom_mtd(str + } + #endif + ++static int rt2800lib_read_eeprom_nvmem(struct rt2x00_dev *rt2x00dev) ++{ ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int len = rt2x00dev->ops->eeprom_size; ++ struct nvmem_cell *cell; ++ const void *data; ++ size_t retlen; ++ int ret = 0; ++ ++ cell = of_nvmem_cell_get(np, "eeprom"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ data = nvmem_cell_read(cell, &retlen); ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ if (retlen != len) { ++ dev_err(rt2x00dev->dev, "invalid eeprom size, required: 0x%04x\n", len); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ memcpy(rt2x00dev->eeprom, data, len); ++ ++ rt2800lib_eeprom_swap(rt2x00dev); ++ ++exit: ++ kfree(data); ++ return ret; ++} ++ + static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) + { +@@ -153,6 +188,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_ + return 0; + #endif + ++ ret = rt2800lib_read_eeprom_nvmem(rt2x00dev); ++ if (!ret) ++ return 0; ++ + return rt2x00lib_read_eeprom_file(rt2x00dev); + } + EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom); diff --git a/patches/rt2x00/603-wifi-rt2x00-Add-support-for-loading-EEPROM-from-devicetree-embedded-data.patch b/patches/rt2x00/603-wifi-rt2x00-Add-support-for-loading-EEPROM-from-devicetree-embedded-data.patch new file mode 100644 index 0000000..9e6cfb4 --- /dev/null +++ b/patches/rt2x00/603-wifi-rt2x00-Add-support-for-loading-EEPROM-from-devicetree-embedded-data.patch @@ -0,0 +1,76 @@ +From adf957124a115bdf3e4728e1ea8c70a632648cf0 Mon Sep 17 00:00:00 2001 +From: Coia Prant +Date: Fri, 14 Feb 2025 15:49:55 +0800 +Subject: [PATCH] wifi: rt2x00: Add support for loading EEPROM from devicetree + embedded data + +This patch allows rt2x00 to load eeprom from devicetree embedded data. + +Example: + +/* load eeprom from embedded data 'eeprom-data' */ +&wmac { + ralink,eeprom-data = <0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff + 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff>; +}; + +Signed-off-by: Coia Prant +--- + .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -33,6 +33,27 @@ static void rt2800lib_eeprom_swap(struct + rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]); + } + ++static int rt2800lib_read_eeprom_data(struct rt2x00_dev *rt2x00dev) ++{ ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int len = rt2x00dev->ops->eeprom_size; ++ const void *data; ++ int size; ++ ++ data = of_get_property(np, "ralink,eeprom-data", &size); ++ if (!data) ++ return -ENOENT; ++ ++ if (size != len) { ++ dev_err(rt2x00dev->dev, "invalid eeprom size, required: 0x%04x\n", len); ++ return -EINVAL; ++ } ++ ++ memcpy(rt2x00dev->eeprom, data, size); ++ ++ return 0; ++} ++ + #if IS_ENABLED(CONFIG_MTD) + static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) + { +@@ -182,6 +203,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_ + { + int ret; + ++ ret = rt2800lib_read_eeprom_data(rt2x00dev); ++ if (!ret) ++ return 0; ++ + #if IS_ENABLED(CONFIG_MTD) + ret = rt2800lib_read_eeprom_mtd(rt2x00dev); + if (!ret) diff --git a/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch b/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch new file mode 100644 index 0000000..7a44d17 --- /dev/null +++ b/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch @@ -0,0 +1,17 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1007,6 +1007,14 @@ static int rt2x00lib_probe_hw_modes(stru + struct ieee80211_rate *rates; + unsigned int num_rates; + unsigned int i; ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int enabled; ++ if (!of_property_read_u32(np, "ralink,2ghz", ++ &enabled) && !enabled) ++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ; ++ if (!of_property_read_u32(np, "ralink,5ghz", ++ &enabled) && !enabled) ++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ; + + num_rates = 0; + if (spec->supported_rates & SUPPORT_RATE_CCK) diff --git a/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch new file mode 100644 index 0000000..570b18d --- /dev/null +++ b/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -0,0 +1,34 @@ +From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 00:03:31 +0100 +Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC + +This patch ads the match table to allow loading the wmac support from a +devicetree. + +Signed-off-by: John Crispin +--- + drivers/net/wireless/ralink/rt2x00/rt2800pci.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -237,10 +237,18 @@ static int bp_rt2x00soc_remove(struct pl + return 0; + } + #endif ++ ++static const struct of_device_id rt2880_wmac_match[] = { ++ { .compatible = "ralink,rt2880-wmac" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_wmac_match); ++ + static struct platform_driver rt2800soc_driver = { + .driver = { + .name = "rt2800_wmac", + .mod_name = KBUILD_MODNAME, ++ .of_match_table = rt2880_wmac_match, + }, + .probe = rt2800soc_probe, + #if LINUX_VERSION_IS_GEQ(6,11,0) diff --git a/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch b/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch new file mode 100644 index 0000000..3adf74f --- /dev/null +++ b/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch @@ -0,0 +1,40 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2800lib.h" +@@ -11276,6 +11277,17 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + ++ { ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int led_polarity; ++ ++ /* Allow overriding polarity from OF */ ++ if (!of_property_read_u32(np, "ralink,led-polarity", ++ &led_polarity)) ++ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY, ++ led_polarity); ++ } ++ + rt2x00dev->led_mcu_reg = eeprom; + #endif /* CPTCFG_RT2X00_LIB_LEDS */ + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c +@@ -98,6 +98,9 @@ static int rt2x00leds_register_led(struc + led->led_dev.name = name; + led->led_dev.brightness = LED_OFF; + ++ if (rt2x00_is_soc(rt2x00dev)) ++ led->led_dev.brightness_set(&led->led_dev, LED_OFF); ++ + retval = led_classdev_register(device, &led->led_dev); + if (retval) { + rt2x00_err(rt2x00dev, "Failed to register led handler\n"); diff --git a/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch b/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch new file mode 100644 index 0000000..64291e8 --- /dev/null +++ b/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1338,7 +1338,7 @@ static inline void rt2x00lib_set_if_comb + */ + if_limit = &rt2x00dev->if_limits_ap; + if_limit->max = rt2x00dev->ops->max_ap_intf; +- if_limit->types = BIT(NL80211_IFTYPE_AP); ++ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION); + #ifdef CPTCFG_MAC80211_MESH + if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); + #endif diff --git a/patches/rt2x00/620-01-rt2x00-respect-rt2800-hardware-TX-queue-index.patch b/patches/rt2x00/620-01-rt2x00-respect-rt2800-hardware-TX-queue-index.patch new file mode 100644 index 0000000..1d88ac7 --- /dev/null +++ b/patches/rt2x00/620-01-rt2x00-respect-rt2800-hardware-TX-queue-index.patch @@ -0,0 +1,257 @@ +From 654653e718f6c55c6f29fd94cc8152a92c8166ac Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Tue, 24 Dec 2024 08:36:32 +0800 +Subject: [PATCH 1/2] rt2x00: respect the rt2800 hardware TX queue index + +The Ralink TX queue register index is different from the Linux +IEEE80211 queue id definition. Their conversion table is as follows: + +Queue IEEE80211 Ralink +AC_VO 0 3 +AC_VI 1 2 +AC_BE 2 0 +AC_BK 3 1 + +The TX queues are still functioning properly under the current +configuration. I don't have evidence, but I believe there should +be some differences in the internal hardware implementation of +different TX queues, e.g. interrupt priority. so it's better to +respect the queue index defined by the Ralink when we construct +the TX rings and descriptors. + +And the more important thing is that we are using the wrong queue +index to calculate the register offset and mask in .conf_tx(), +which resulted in writing incorrect AIFSN, CWMAX, CWMIN and TXOP +values for all TX queues. This patch introduces a index conversion +table to fix these parameters. + +Signed-off-by: Shiji Yang +--- + drivers/net/wireless/ralink/rt2x00/rt2800.h | 24 ++++++------ + .../net/wireless/ralink/rt2x00/rt2800lib.c | 20 +++++++--- + .../net/wireless/ralink/rt2x00/rt2800mmio.c | 38 ++++++++++--------- + .../net/wireless/ralink/rt2x00/rt2x00queue.h | 20 ++++++++++ + 4 files changed, 67 insertions(+), 35 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h +@@ -379,10 +379,10 @@ + + /* + * WMM_AIFSN_CFG: Aifsn for each EDCA AC +- * AIFSN0: AC_VO +- * AIFSN1: AC_VI +- * AIFSN2: AC_BE +- * AIFSN3: AC_BK ++ * AIFSN0: AC_BE ++ * AIFSN1: AC_BK ++ * AIFSN2: AC_VI ++ * AIFSN3: AC_VO + */ + #define WMM_AIFSN_CFG 0x0214 + #define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) +@@ -392,10 +392,10 @@ + + /* + * WMM_CWMIN_CSR: CWmin for each EDCA AC +- * CWMIN0: AC_VO +- * CWMIN1: AC_VI +- * CWMIN2: AC_BE +- * CWMIN3: AC_BK ++ * CWMIN0: AC_BE ++ * CWMIN1: AC_BK ++ * CWMIN2: AC_VI ++ * CWMIN3: AC_VO + */ + #define WMM_CWMIN_CFG 0x0218 + #define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) +@@ -405,10 +405,10 @@ + + /* + * WMM_CWMAX_CSR: CWmax for each EDCA AC +- * CWMAX0: AC_VO +- * CWMAX1: AC_VI +- * CWMAX2: AC_BE +- * CWMAX3: AC_BK ++ * CWMAX0: AC_BE ++ * CWMAX1: AC_BK ++ * CWMAX2: AC_VI ++ * CWMAX3: AC_VO + */ + #define WMM_CWMAX_CFG 0x021c + #define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -835,7 +835,8 @@ void rt2800_write_tx_data(struct queue_e + txdesc->key_idx : txdesc->u.ht.wcid); + rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, + txdesc->length); +- rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); ++ rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, ++ rt2x00_ac_to_hwq(entry->queue->qid)); + rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1); + rt2x00_desc_write(txwi, 1, word); + +@@ -1125,6 +1126,12 @@ void rt2800_txdone(struct rt2x00_dev *rt + u32 reg; + u8 qid; + bool match; ++ static const u8 rt2ac[] = { ++ IEEE80211_AC_BE, ++ IEEE80211_AC_BK, ++ IEEE80211_AC_VI, ++ IEEE80211_AC_VO, ++ }; + + while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { + /* +@@ -1132,6 +1139,8 @@ void rt2800_txdone(struct rt2x00_dev *rt + * guaranteed to be one of the TX QIDs . + */ + qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); ++ /* Convert Ralink hardware queue index to IEEE80211 queue id. */ ++ qid = rt2ac[qid]; + queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); + + if (unlikely(rt2x00queue_empty(queue))) { +@@ -12182,8 +12191,9 @@ int rt2800_conf_tx(struct ieee80211_hw * + queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); + + /* Update WMM TXOP register */ +- offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); +- field.bit_offset = (queue_idx & 1) * 16; ++ offset = WMM_TXOP0_CFG + ++ (sizeof(u32) * (!!(rt2x00_ac_to_hwq(queue_idx) & 2))); ++ field.bit_offset = (rt2x00_ac_to_hwq(queue_idx) & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + reg = rt2800_register_read(rt2x00dev, offset); +@@ -12191,7 +12201,7 @@ int rt2800_conf_tx(struct ieee80211_hw * + rt2800_register_write(rt2x00dev, offset, reg); + + /* Update WMM registers */ +- field.bit_offset = queue_idx * 4; ++ field.bit_offset = rt2x00_ac_to_hwq(queue_idx) * 4; + field.bit_mask = 0xf << field.bit_offset; + + reg = rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG); +@@ -12207,7 +12217,7 @@ int rt2800_conf_tx(struct ieee80211_hw * + rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); + + /* Update EDCA registers */ +- offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); ++ offset = EDCA_AC0_CFG + (sizeof(u32) * rt2x00_ac_to_hwq(queue_idx)); + + reg = rt2800_register_read(rt2x00dev, offset); + rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); +--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c +@@ -35,7 +35,7 @@ unsigned int rt2800mmio_get_dma_done(str + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: +- qid = queue->qid; ++ qid = rt2x00_ac_to_hwq(queue->qid); + idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(qid)); + break; + case QID_MGMT: +@@ -456,6 +456,7 @@ void rt2800mmio_kick_queue(struct data_q + { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + struct queue_entry *entry; ++ u8 qid; + + switch (queue->qid) { + case QID_AC_VO: +@@ -464,7 +465,8 @@ void rt2800mmio_kick_queue(struct data_q + case QID_AC_BK: + WARN_ON_ONCE(rt2x00queue_empty(queue)); + entry = rt2x00queue_get_entry(queue, Q_INDEX); +- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), ++ qid = rt2x00_ac_to_hwq(queue->qid); ++ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(qid), + entry->entry_idx); + hrtimer_start(&rt2x00dev->txstatus_timer, + TXSTATUS_TIMEOUT, HRTIMER_MODE_REL); +@@ -666,36 +668,36 @@ int rt2800mmio_init_queues(struct rt2x00 + * Initialize registers. + */ + entry_priv = rt2x00dev->tx[0].entries[0].priv_data; +- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, ++ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, + entry_priv->desc_dma); +- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, ++ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, + rt2x00dev->tx[0].limit); +- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); +- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); + + entry_priv = rt2x00dev->tx[1].entries[0].priv_data; +- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, ++ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, + entry_priv->desc_dma); +- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, ++ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, + rt2x00dev->tx[1].limit); +- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); +- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); + + entry_priv = rt2x00dev->tx[2].entries[0].priv_data; +- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, ++ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, + entry_priv->desc_dma); +- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, ++ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, + rt2x00dev->tx[2].limit); +- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); +- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); + + entry_priv = rt2x00dev->tx[3].entries[0].priv_data; +- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, ++ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, + entry_priv->desc_dma); +- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, ++ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, + rt2x00dev->tx[3].limit); +- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); +- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); ++ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); + + rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); + rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h +@@ -57,6 +57,26 @@ enum data_queue_qid { + }; + + /** ++ * rt2x00_ac_to_hwq - Convert IEEE80211 queue id to Ralink hardware ++ * queue register index. ++ * @ac: TX queue id. ++ */ ++static inline u8 rt2x00_ac_to_hwq(enum data_queue_qid ac) ++{ ++ static const u8 ralink_queue_map[] = { ++ [IEEE80211_AC_BE] = 0, ++ [IEEE80211_AC_BK] = 1, ++ [IEEE80211_AC_VI] = 2, ++ [IEEE80211_AC_VO] = 3, ++ }; ++ ++ if (unlikely(ac >= IEEE80211_NUM_ACS)) ++ return ac; ++ ++ return ralink_queue_map[ac]; ++} ++ ++/** + * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc + * + * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX diff --git a/patches/rt2x00/620-02-rt2x00-increase-the-watchdog-sampling-frequency.patch b/patches/rt2x00/620-02-rt2x00-increase-the-watchdog-sampling-frequency.patch new file mode 100644 index 0000000..c60d2ad --- /dev/null +++ b/patches/rt2x00/620-02-rt2x00-increase-the-watchdog-sampling-frequency.patch @@ -0,0 +1,74 @@ +From aec50d1a30349759de0ac535f54c3441bf7ebef7 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 2/2] rt2x00: increase the watchdog sampling frequency + +Increase the sampling frequency of the watchdog when the hung +counter reaches the threshold to avoid some unnecessary resets. + +Signed-off-by: Shiji Yang +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 45 +++++++++++++------ + 1 file changed, 32 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1320,26 +1320,45 @@ static bool rt2800_watchdog_hung(struct + return true; + } + ++static inline bool check_dma_busy_rx(u32 reg_cfg, u32 reg_int) ++{ ++ return (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_RX_DMA_BUSY) && ++ rt2x00_get_field32(reg_int, INT_SOURCE_CSR_RX_COHERENT)); ++} ++ ++static inline bool check_dma_busy_tx(u32 reg_cfg, u32 reg_int) ++{ ++ return (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_TX_DMA_BUSY) && ++ rt2x00_get_field32(reg_int, INT_SOURCE_CSR_TX_COHERENT)); ++} ++ + static bool rt2800_watchdog_dma_busy(struct rt2x00_dev *rt2x00dev) + { + bool busy_rx, busy_tx; + u32 reg_cfg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG); + u32 reg_int = rt2800_register_read(rt2x00dev, INT_SOURCE_CSR); + +- if (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_RX_DMA_BUSY) && +- rt2x00_get_field32(reg_int, INT_SOURCE_CSR_RX_COHERENT)) +- rt2x00dev->rxdma_busy++; +- else +- rt2x00dev->rxdma_busy = 0; +- +- if (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_TX_DMA_BUSY) && +- rt2x00_get_field32(reg_int, INT_SOURCE_CSR_TX_COHERENT)) +- rt2x00dev->txdma_busy++; +- else +- rt2x00dev->txdma_busy = 0; ++ rt2x00dev->rxdma_busy = check_dma_busy_rx(reg_cfg, reg_int) ? ++ rt2x00dev->rxdma_busy + 1 : 0; ++ rt2x00dev->txdma_busy = check_dma_busy_tx(reg_cfg, reg_int) ? ++ rt2x00dev->txdma_busy + 1 : 0; ++ ++ if (rt2x00dev->rxdma_busy > 25 || rt2x00dev->txdma_busy > 25) { ++ int cnt; ++ for (cnt = 0; cnt < 10; cnt++) { ++ msleep(5); ++ reg_cfg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG); ++ reg_int = rt2800_register_read(rt2x00dev, INT_SOURCE_CSR); ++ ++ if (!check_dma_busy_rx(reg_cfg, reg_int)) ++ rt2x00dev->rxdma_busy = 0; ++ if (!check_dma_busy_tx(reg_cfg, reg_int)) ++ rt2x00dev->txdma_busy = 0; ++ } ++ } + +- busy_rx = rt2x00dev->rxdma_busy > 30; +- busy_tx = rt2x00dev->txdma_busy > 30; ++ busy_rx = rt2x00dev->rxdma_busy > 40; ++ busy_tx = rt2x00dev->txdma_busy > 40; + + if (!busy_rx && !busy_tx) + return false; diff --git a/patches/rt2x00/621-01-rt2x00-always-calibrate-MT7620-when-switching-channe.patch b/patches/rt2x00/621-01-rt2x00-always-calibrate-MT7620-when-switching-channe.patch new file mode 100644 index 0000000..01ae04e --- /dev/null +++ b/patches/rt2x00/621-01-rt2x00-always-calibrate-MT7620-when-switching-channe.patch @@ -0,0 +1,77 @@ +From 2c5aad0f9990724cce48e0a53b66bc0438e4603d Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 1/4] rt2x00: always calibrate MT7620 when switching channel + +Perform calibration work after each channel switching operation. +This should help improve the rx/tx signal strength for MT7620. + +Signed-off-by: Shiji Yang +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 24 ++++++++++++++----- + 1 file changed, 18 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -5704,6 +5704,9 @@ static void rt2800_config_ps(struct rt2x + } + } + ++static void rt2800_calibration_rt6352_stage1(struct rt2x00_dev *rt2x00dev); ++static void rt2800_calibration_rt6352_stage2(struct rt2x00_dev *rt2x00dev); ++ + void rt2800_config(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags) +@@ -5718,10 +5721,18 @@ void rt2800_config(struct rt2x00_dev *rt + */ + rt2800_update_survey(rt2x00dev); + ++ if (rt2x00_rt(rt2x00dev, RT6352) && ++ !test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) ++ rt2800_calibration_rt6352_stage1(rt2x00dev); ++ + rt2800_config_channel(rt2x00dev, libconf->conf, + &libconf->rf, &libconf->channel); + rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan, + libconf->conf->power_level); ++ ++ if (rt2x00_rt(rt2x00dev, RT6352) && ++ !test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) ++ rt2800_calibration_rt6352_stage2(rt2x00dev); + } + if (flags & IEEE80211_CONF_CHANGE_POWER) + rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan, +@@ -10421,15 +10432,19 @@ static void rt2800_restore_rf_bbp_rt6352 + } + } + +-static void rt2800_calibration_rt6352(struct rt2x00_dev *rt2x00dev) ++static void rt2800_calibration_rt6352_stage1(struct rt2x00_dev *rt2x00dev) + { +- u32 reg; +- + if (rt2x00_has_cap_external_pa(rt2x00dev) || + rt2x00_has_cap_external_lna_bg(rt2x00dev)) + rt2800_restore_rf_bbp_rt6352(rt2x00dev); + + rt2800_r_calibration(rt2x00dev); ++} ++ ++static void rt2800_calibration_rt6352_stage2(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ + rt2800_rf_self_txdc_cal(rt2x00dev); + rt2800_rxdcoc_calibration(rt2x00dev); + rt2800_bw_filter_calibration(rt2x00dev, true); +@@ -10760,9 +10775,6 @@ static void rt2800_init_rfcsr_6352(struc + + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); +- +- /* Do calibration and init PA/LNA */ +- rt2800_calibration_rt6352(rt2x00dev); + } + + static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) diff --git a/patches/rt2x00/621-02-rt2x00-rework-link-tuner-for-MT7620.patch b/patches/rt2x00/621-02-rt2x00-rework-link-tuner-for-MT7620.patch new file mode 100644 index 0000000..f7e7a8e --- /dev/null +++ b/patches/rt2x00/621-02-rt2x00-rework-link-tuner-for-MT7620.patch @@ -0,0 +1,48 @@ +From aaa57924324c1ee77afa5e3effc95cc86158ddcc Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 2/4] rt2x00: rework link tuner for MT7620 + +Correct the VGC gain value for MT7620 and only do gain calibration +for supported devices. + +Signed-off-by: Shiji Yang +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -5561,6 +5561,9 @@ static void rt2800_config_txpower(struct + + void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) + { ++ if (rt2x00_rt(rt2x00dev, RT6352)) ++ return; ++ + rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan, + rt2x00dev->tx_power); + } +@@ -5773,9 +5776,10 @@ static u8 rt2800_get_default_vgc(struct + rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392) || +- rt2x00_rt(rt2x00dev, RT5592) || +- rt2x00_rt(rt2x00dev, RT6352)) ++ rt2x00_rt(rt2x00dev, RT5592)) + vgc = 0x1c + (2 * rt2x00dev->lna_gain); ++ else if(rt2x00_rt(rt2x00dev, RT6352)) ++ vgc = 0x04 + (2 * rt2x00dev->lna_gain); + else + vgc = 0x2e + rt2x00dev->lna_gain; + } else { /* 5GHZ band */ +@@ -5828,7 +5832,8 @@ void rt2800_link_tuner(struct rt2x00_dev + { + u8 vgc; + +- if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) ++ if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C) || ++ rt2x00_rt(rt2x00dev, RT6352)) + return; + + /* When RSSI is better than a certain threshold, increase VGC diff --git a/patches/rt2x00/621-03-rt2x00-correct-MT7620-SDM-mode-register-value.patch b/patches/rt2x00/621-03-rt2x00-correct-MT7620-SDM-mode-register-value.patch new file mode 100644 index 0000000..7c376df --- /dev/null +++ b/patches/rt2x00/621-03-rt2x00-correct-MT7620-SDM-mode-register-value.patch @@ -0,0 +1,25 @@ +From b672507ca9f06bb17213036b16bc4f5c5bc65357 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 3/4] rt2x00: correct MT7620 SDM mode register value + +rt2x00_set_field8() is a mask writing function. If we want to set +the BIT(7) for the SDM mode register here, we only need to fill "4" +in the mask. + +Signed-off-by: Shiji Yang +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -3848,7 +3848,7 @@ static void rt2800_config_channel_rf7620 + + /* Default: XO=20MHz , SDM mode */ + rfcsr = rt2800_rfcsr_read(rt2x00dev, 16); +- rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80); ++ rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 4); + rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 21); diff --git a/patches/rt2x00/621-04-rt2x00-fix-register-operation-on-RXIQ-calibration.patch b/patches/rt2x00/621-04-rt2x00-fix-register-operation-on-RXIQ-calibration.patch new file mode 100644 index 0000000..0e0245e --- /dev/null +++ b/patches/rt2x00/621-04-rt2x00-fix-register-operation-on-RXIQ-calibration.patch @@ -0,0 +1,26 @@ +From 2585ada646e4dcf152ab813a24d667e6903105f4 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 4/4] rt2x00: fix register operation on RXIQ calibration + +In rt2800_rxiq_calibration(), some variables are overwritten +before being used. Based on the values of the relevant registers +in other functions, I believe the correct operation should be +bit mask writing. + +Signed-off-by: Shiji Yang +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -8846,7 +8846,7 @@ static void rt2800_rxiq_calibration(stru + rt2x00_warn(rt2x00dev, "Timeout waiting for MAC status in RXIQ calibration\n"); + + bbpval = bbp4 & (~0x18); +- bbpval = bbp4 | 0x00; ++ bbpval = bbpval | 0x00; + rt2800_bbp_write(rt2x00dev, 4, bbpval); + + bbpval = rt2800_bbp_read(rt2x00dev, 21); diff --git a/patches/rt2x00/622-01-rt2x00-fix-RFCSR-register-init-values-for-RT5592.patch b/patches/rt2x00/622-01-rt2x00-fix-RFCSR-register-init-values-for-RT5592.patch new file mode 100644 index 0000000..72a8f00 --- /dev/null +++ b/patches/rt2x00/622-01-rt2x00-fix-RFCSR-register-init-values-for-RT5592.patch @@ -0,0 +1,230 @@ +From b48887d5de9921d0ff9e88068e3cd555a383d702 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 1/2] rt2x00: fix RFCSR register init values for RT5592 + +Based on Raink proprietary driver 2.7.1.5, correct the initial +values of some RFCSR registers for RT5592. + +Signed-off-by: Shiji Yang +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 122 ++++++++---------- + 1 file changed, 53 insertions(+), 69 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -3576,9 +3576,8 @@ static void rt2800_config_channel_rf55xx + + /* TODO RF27 <- tssi */ + +- rfcsr = rf->channel <= 10 ? 0x07 : 0x06; +- rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); +- rt2800_rfcsr_write(rt2x00dev, 59, rfcsr); ++ rt2800_rfcsr_write(rt2x00dev, 23, rf->channel <= 10 ? 0x08 : 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 59, rf->channel <= 4 ? 0x06 : 0x04); + + if (is_11b) { + /* CCK */ +@@ -3599,7 +3598,7 @@ static void rt2800_config_channel_rf55xx + power_bound = POWER_BOUND; + ep_reg = 0x2; + } else { +- rt2800_rfcsr_write(rt2x00dev, 10, 0x97); ++ rt2800_rfcsr_write(rt2x00dev, 10, 0x95); + /* FIMXE: RF11 overwrite */ + rt2800_rfcsr_write(rt2x00dev, 11, 0x40); + rt2800_rfcsr_write(rt2x00dev, 25, 0xBF); +@@ -3608,13 +3607,15 @@ static void rt2800_config_channel_rf55xx + rt2800_rfcsr_write(rt2x00dev, 37, 0x04); + rt2800_rfcsr_write(rt2x00dev, 38, 0x85); + rt2800_rfcsr_write(rt2x00dev, 40, 0x42); +- rt2800_rfcsr_write(rt2x00dev, 41, 0xBB); ++ rt2800_rfcsr_write(rt2x00dev, 41, 0xAB); + rt2800_rfcsr_write(rt2x00dev, 42, 0xD7); +- rt2800_rfcsr_write(rt2x00dev, 45, 0x41); ++ rt2800_rfcsr_write(rt2x00dev, 45, 0x01); + rt2800_rfcsr_write(rt2x00dev, 48, 0x00); + rt2800_rfcsr_write(rt2x00dev, 57, 0x77); ++ rt2800_rfcsr_write(rt2x00dev, 58, 0x19); + rt2800_rfcsr_write(rt2x00dev, 60, 0x05); + rt2800_rfcsr_write(rt2x00dev, 61, 0x01); ++ rt2800_rfcsr_write(rt2x00dev, 62, 0x19); + + /* TODO RF27 <- tssi */ + +@@ -3623,82 +3624,59 @@ static void rt2800_config_channel_rf55xx + rt2800_rfcsr_write(rt2x00dev, 12, 0x2E); + rt2800_rfcsr_write(rt2x00dev, 13, 0x22); + rt2800_rfcsr_write(rt2x00dev, 22, 0x60); +- rt2800_rfcsr_write(rt2x00dev, 23, 0x7F); +- if (rf->channel <= 50) +- rt2800_rfcsr_write(rt2x00dev, 24, 0x09); +- else if (rf->channel >= 52) +- rt2800_rfcsr_write(rt2x00dev, 24, 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x7E); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x07); + rt2800_rfcsr_write(rt2x00dev, 39, 0x1C); + rt2800_rfcsr_write(rt2x00dev, 43, 0x5B); +- rt2800_rfcsr_write(rt2x00dev, 44, 0X40); + rt2800_rfcsr_write(rt2x00dev, 46, 0X00); +- rt2800_rfcsr_write(rt2x00dev, 51, 0xFE); +- rt2800_rfcsr_write(rt2x00dev, 52, 0x0C); +- rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); ++ rt2800_rfcsr_write(rt2x00dev, 51, 0xFD); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x0E); ++ rt2800_rfcsr_write(rt2x00dev, 55, 0x04); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); ++ rt2800_rfcsr_write(rt2x00dev, 59, 0x7C); ++ + if (rf->channel <= 50) { +- rt2800_rfcsr_write(rt2x00dev, 55, 0x06); +- rt2800_rfcsr_write(rt2x00dev, 56, 0xD3); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0X32); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0xF9); + } else if (rf->channel >= 52) { +- rt2800_rfcsr_write(rt2x00dev, 55, 0x04); +- rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0X2A); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); + } +- +- rt2800_rfcsr_write(rt2x00dev, 58, 0x15); +- rt2800_rfcsr_write(rt2x00dev, 59, 0x7F); +- rt2800_rfcsr_write(rt2x00dev, 62, 0x15); +- + } else if (rf->channel >= 100 && rf->channel <= 165) { +- + rt2800_rfcsr_write(rt2x00dev, 12, 0x0E); + rt2800_rfcsr_write(rt2x00dev, 13, 0x42); + rt2800_rfcsr_write(rt2x00dev, 22, 0x40); +- if (rf->channel <= 153) { +- rt2800_rfcsr_write(rt2x00dev, 23, 0x3C); +- rt2800_rfcsr_write(rt2x00dev, 24, 0x06); +- } else if (rf->channel >= 155) { +- rt2800_rfcsr_write(rt2x00dev, 23, 0x38); +- rt2800_rfcsr_write(rt2x00dev, 24, 0x05); +- } ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x06); ++ rt2800_rfcsr_write(rt2x00dev, 55, 0x01); ++ + if (rf->channel <= 138) { ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x7C); + rt2800_rfcsr_write(rt2x00dev, 39, 0x1A); + rt2800_rfcsr_write(rt2x00dev, 43, 0x3B); +- rt2800_rfcsr_write(rt2x00dev, 44, 0x20); + rt2800_rfcsr_write(rt2x00dev, 46, 0x18); +- } else if (rf->channel >= 140) { ++ } else { ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x78); + rt2800_rfcsr_write(rt2x00dev, 39, 0x18); + rt2800_rfcsr_write(rt2x00dev, 43, 0x1B); +- rt2800_rfcsr_write(rt2x00dev, 44, 0x10); + rt2800_rfcsr_write(rt2x00dev, 46, 0X08); + } +- if (rf->channel <= 124) +- rt2800_rfcsr_write(rt2x00dev, 51, 0xFC); +- else if (rf->channel >= 126) +- rt2800_rfcsr_write(rt2x00dev, 51, 0xEC); +- if (rf->channel <= 138) +- rt2800_rfcsr_write(rt2x00dev, 52, 0x06); +- else if (rf->channel >= 140) +- rt2800_rfcsr_write(rt2x00dev, 52, 0x06); +- rt2800_rfcsr_write(rt2x00dev, 54, 0xEB); +- if (rf->channel <= 138) +- rt2800_rfcsr_write(rt2x00dev, 55, 0x01); +- else if (rf->channel >= 140) +- rt2800_rfcsr_write(rt2x00dev, 55, 0x00); +- if (rf->channel <= 128) +- rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); +- else if (rf->channel >= 130) +- rt2800_rfcsr_write(rt2x00dev, 56, 0xAB); +- if (rf->channel <= 116) +- rt2800_rfcsr_write(rt2x00dev, 58, 0x1D); +- else if (rf->channel >= 118) +- rt2800_rfcsr_write(rt2x00dev, 58, 0x15); +- if (rf->channel <= 138) +- rt2800_rfcsr_write(rt2x00dev, 59, 0x3F); +- else if (rf->channel >= 140) +- rt2800_rfcsr_write(rt2x00dev, 59, 0x7C); +- if (rf->channel <= 116) +- rt2800_rfcsr_write(rt2x00dev, 62, 0x1D); +- else if (rf->channel >= 118) +- rt2800_rfcsr_write(rt2x00dev, 62, 0x15); ++ ++ if (rf->channel <= 114) { ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x02); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x1A); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0xEA); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0xB3); ++ } else { ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x0A); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0xF9); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0x9B); ++ } ++ ++ rt2800_rfcsr_write(rt2x00dev, 51, rf->channel <= 124 ? 0xFC : 0xEC); ++ rt2800_rfcsr_write(rt2x00dev, 58, rf->channel <= 116 ? 0x1D : 0x15); ++ rfcsr = (rf->channel >= 116 && rf->channel <= 138) ? 0x7E : 0x7C; ++ rt2800_rfcsr_write(rt2x00dev, 59, rfcsr); + } + + power_bound = POWER_BOUND_5G; +@@ -3710,7 +3688,7 @@ static void rt2800_config_channel_rf55xx + rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound); + else + rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +- if (is_type_ep) ++ if (!is_type_ep) + rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg); + rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +@@ -3719,7 +3697,7 @@ static void rt2800_config_channel_rf55xx + rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound); + else + rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); +- if (is_type_ep) ++ if (!is_type_ep) + rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg); + rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +@@ -3740,7 +3718,6 @@ static void rt2800_config_channel_rf55xx + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +- rt2800_rfcsr_write(rt2x00dev, 6, 0xe4); + + if (conf_is_ht40(conf)) + rt2800_rfcsr_write(rt2x00dev, 30, 0x16); +@@ -8505,12 +8482,15 @@ static void rt2800_init_rfcsr_5392(struc + + static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) + { ++ u16 eeprom; ++ + rt2800_rf_init_calibration(rt2x00dev, 30); + + rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); ++ rt2800_rfcsr_write(rt2x00dev, 2, 0x80); + rt2800_rfcsr_write(rt2x00dev, 3, 0x08); + rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +- rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); ++ rt2800_rfcsr_write(rt2x00dev, 6, 0xE0); + rt2800_rfcsr_write(rt2x00dev, 7, 0x00); + rt2800_rfcsr_write(rt2x00dev, 14, 0x00); + rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +@@ -8526,9 +8506,13 @@ static void rt2800_init_rfcsr_5592(struc + rt2800_rfcsr_write(rt2x00dev, 34, 0x07); + rt2800_rfcsr_write(rt2x00dev, 35, 0x12); + rt2800_rfcsr_write(rt2x00dev, 47, 0x0C); +- rt2800_rfcsr_write(rt2x00dev, 53, 0x22); ++ rt2800_rfcsr_write(rt2x00dev, 53, 0x44); + rt2800_rfcsr_write(rt2x00dev, 63, 0x07); + ++ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF2); ++ if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF2_CRYSTAL)) ++ rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); ++ + rt2800_rfcsr_write(rt2x00dev, 2, 0x80); + msleep(1); + diff --git a/patches/rt2x00/622-02-rt2x00-fix-BBP-register-init-values-for-RT5592.patch b/patches/rt2x00/622-02-rt2x00-fix-BBP-register-init-values-for-RT5592.patch new file mode 100644 index 0000000..19d1951 --- /dev/null +++ b/patches/rt2x00/622-02-rt2x00-fix-BBP-register-init-values-for-RT5592.patch @@ -0,0 +1,119 @@ +From 1847d817df5585f9d957d16ed2a56ceb41cf6df7 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 22 Dec 2024 17:06:59 +0800 +Subject: [PATCH 2/2] rt2x00: fix BBP register init values for RT5592 + +Based on Raink proprietary driver 2.7.1.5, correct the initial +values of some BBP registers for RT5592. + +Signed-off-by: Shiji Yang +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 32 +++++++++---------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -3746,6 +3746,7 @@ static void rt2800_config_channel_rf55xx + rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08); + rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38); + rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92); ++ rt2800_bbp_write(rt2x00dev, 95, (rf->channel <= 14) ? 0x9A : 0x1A); + + /* GLRT band configuration */ + rt2800_bbp_write(rt2x00dev, 195, 128); +@@ -3758,7 +3759,7 @@ static void rt2800_config_channel_rf55xx + rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20); + rt2800_bbp_write(rt2x00dev, 195, 133); + rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F); +- rt2800_bbp_write(rt2x00dev, 195, 124); ++ rt2800_bbp_write(rt2x00dev, 195, 134); + rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); + } + +@@ -4304,7 +4305,8 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +- if (rt2x00_rt(rt2x00dev, RT6352)) ++ if (rt2x00_rt(rt2x00dev, RT5592) || ++ rt2x00_rt(rt2x00dev, RT6352)) + rt2800_bbp_write(rt2x00dev, 86, 0x38); + else + rt2800_bbp_write(rt2x00dev, 86, 0); +@@ -4313,6 +4315,7 @@ static void rt2800_config_channel(struct + if (rf->channel <= 14) { + if (!rt2x00_rt(rt2x00dev, RT5390) && + !rt2x00_rt(rt2x00dev, RT5392) && ++ !rt2x00_rt(rt2x00dev, RT5592) && + !rt2x00_rt(rt2x00dev, RT6352)) { + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_bbp_write(rt2x00dev, 82, 0x62); +@@ -4336,17 +4339,20 @@ static void rt2800_config_channel(struct + else if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 82, 0x82); +- else if (!rt2x00_rt(rt2x00dev, RT6352)) ++ else if (!rt2x00_rt(rt2x00dev, RT5592) && ++ !rt2x00_rt(rt2x00dev, RT6352)) + rt2800_bbp_write(rt2x00dev, 82, 0xf2); + + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 83, 0x9a); + +- if (rt2x00_has_cap_external_lna_a(rt2x00dev)) +- rt2800_bbp_write(rt2x00dev, 75, 0x46); +- else +- rt2800_bbp_write(rt2x00dev, 75, 0x50); ++ if (!rt2x00_rt(rt2x00dev, RT5592)) { ++ if (rt2x00_has_cap_external_lna_a(rt2x00dev)) ++ rt2800_bbp_write(rt2x00dev, 75, 0x46); ++ else ++ rt2800_bbp_write(rt2x00dev, 75, 0x50); ++ } + } + + reg = rt2800_register_read(rt2x00dev, TX_BAND_CFG); +@@ -5783,12 +5789,10 @@ static inline void rt2800_set_vgc(struct + if (rt2x00_rt(rt2x00dev, RT3572) || + rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883) || ++ rt2x00_rt(rt2x00dev, RT5592) || + rt2x00_rt(rt2x00dev, RT6352)) { + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, + vgc_level); +- } else if (rt2x00_rt(rt2x00dev, RT5592)) { +- rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); +- rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); + } else { + rt2800_bbp_write(rt2x00dev, 66, vgc_level); + } +@@ -7016,7 +7020,6 @@ static void rt2800_init_bbp_5592(struct + rt2800_bbp_write(rt2x00dev, 88, 0x90); + rt2800_bbp_write(rt2x00dev, 91, 0x04); + rt2800_bbp_write(rt2x00dev, 92, 0x02); +- rt2800_bbp_write(rt2x00dev, 95, 0x9a); + rt2800_bbp_write(rt2x00dev, 98, 0x12); + rt2800_bbp_write(rt2x00dev, 103, 0xC0); + rt2800_bbp_write(rt2x00dev, 104, 0x92); +@@ -7027,6 +7030,7 @@ static void rt2800_init_bbp_5592(struct + rt2800_bbp_write(rt2x00dev, 134, 0xD0); + rt2800_bbp_write(rt2x00dev, 135, 0xF6); + rt2800_bbp_write(rt2x00dev, 137, 0x0F); ++ rt2800_bbp_write(rt2x00dev, 148, 0x84); + + /* Initialize GLRT (Generalized Likehood Radio Test) */ + rt2800_init_bbp_5592_glrt(rt2x00dev); +@@ -7051,12 +7055,6 @@ static void rt2800_init_bbp_5592(struct + rt2x00_set_field8(&value, BBP254_BIT7, 1); + rt2800_bbp_write(rt2x00dev, 254, value); + } +- +- rt2800_init_freq_calibration(rt2x00dev); +- +- rt2800_bbp_write(rt2x00dev, 84, 0x19); +- if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) +- rt2800_bbp_write(rt2x00dev, 103, 0xc0); + } + + static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev) diff --git a/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch b/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch new file mode 100644 index 0000000..c188940 --- /dev/null +++ b/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch @@ -0,0 +1,121 @@ +From 0fce1109f894ec7fcd72cb098843a1eff786716a Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 16 Sep 2022 20:49:42 +0100 +Subject: [PATCH 16/16] rt2x00: import support for external LNA on MT7620 +To: linux-wireless@vger.kernel.org, + Stanislaw Gruszka , + Helmut Schaa +Cc: Kalle Valo , + David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Johannes Berg + +In order to carry out calibration on boards with ePA or eLNA the PA pin +needs to be switch to GPIO mode on MT7620. Implement that by selecting +pinctrl state "pa_gpio" which should be defined for MT7620 boards with +eLNA or ePA beside the "default" state. + +Reported-by: Serge Vasilugin +Signed-off-by: Daniel Golle +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 58 +++++++++++++++++++ + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 5 ++ + .../net/wireless/ralink/rt2x00/rt2x00soc.c | 15 +++++ + 3 files changed, 78 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -305,6 +305,24 @@ static void rt2800_rf_write(struct rt2x0 + mutex_unlock(&rt2x00dev->csr_mutex); + } + ++static void rt6352_enable_pa_pin(struct rt2x00_dev *rt2x00dev, int enable) ++{ ++ if (!rt2x00dev->pinctrl) ++ return; ++ ++ if (enable) { ++ if (!rt2x00dev->pins_default) ++ return; ++ ++ pinctrl_select_state(rt2x00dev->pinctrl, rt2x00dev->pins_default); ++ } else { ++ if (!rt2x00dev->pins_pa_gpio) ++ return; ++ ++ pinctrl_select_state(rt2x00dev->pinctrl, rt2x00dev->pins_pa_gpio); ++ } ++} ++ + static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { + [EEPROM_CHIP_ID] = 0x0000, + [EEPROM_VERSION] = 0x0001, +@@ -10422,8 +10440,10 @@ static void rt2800_restore_rf_bbp_rt6352 + static void rt2800_calibration_rt6352_stage1(struct rt2x00_dev *rt2x00dev) + { + if (rt2x00_has_cap_external_pa(rt2x00dev) || +- rt2x00_has_cap_external_lna_bg(rt2x00dev)) ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt6352_enable_pa_pin(rt2x00dev, 0); + rt2800_restore_rf_bbp_rt6352(rt2x00dev); ++ } + + rt2800_r_calibration(rt2x00dev); + } +@@ -10447,6 +10467,8 @@ static void rt2800_calibration_rt6352_st + !rt2x00_has_cap_external_lna_bg(rt2x00dev)) + return; + ++ rt6352_enable_pa_pin(rt2x00dev, 1); ++ + if (rt2x00_has_cap_external_pa(rt2x00dev)) { + reg = rt2800_register_read(rt2x00dev, RF_CONTROL3); + reg |= 0x00000101; +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1015,6 +1016,11 @@ struct rt2x00_dev { + + /* Clock for System On Chip devices. */ + struct clk *clk; ++ ++ /* pinctrl and states for System On Chip devices with PA/LNA. */ ++ struct pinctrl *pinctrl; ++ struct pinctrl_state *pins_default; ++ struct pinctrl_state *pins_pa_gpio; + }; + + struct rt2x00_bar_list_entry { +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c +@@ -97,6 +97,21 @@ int rt2x00soc_probe(struct platform_devi + if (retval) + goto exit_free_reg; + ++ rt2x00dev->pinctrl = devm_pinctrl_get(&pdev->dev); ++ if (IS_ERR(rt2x00dev->pinctrl)) { ++ rt2x00dev->pinctrl = NULL; ++ rt2x00dev->pins_default = NULL; ++ rt2x00dev->pins_pa_gpio = NULL; ++ } else { ++ rt2x00dev->pins_default = pinctrl_lookup_state(rt2x00dev->pinctrl, "default"); ++ if (IS_ERR(rt2x00dev->pins_default)) ++ rt2x00dev->pins_default = NULL; ++ ++ rt2x00dev->pins_pa_gpio = pinctrl_lookup_state(rt2x00dev->pinctrl, "pa_gpio"); ++ if (IS_ERR(rt2x00dev->pins_pa_gpio)) ++ rt2x00dev->pins_pa_gpio = NULL; ++ } ++ + return 0; + + exit_free_reg: diff --git a/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch b/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch new file mode 100644 index 0000000..cb7a361 --- /dev/null +++ b/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch @@ -0,0 +1,139 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -76,6 +76,9 @@ struct rt2800_ops { + int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); + __le32 *(*drv_get_txwi)(struct queue_entry *entry); + unsigned int (*drv_get_dma_done)(struct data_queue *queue); ++ int (*hw_get_chippkg)(void); ++ int (*hw_get_chipver)(void); ++ int (*hw_get_chipeco)(void); + }; + + static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev, +@@ -184,6 +187,27 @@ static inline unsigned int rt2800_drv_ge + return rt2800ops->drv_get_dma_done(queue); + } + ++static inline int rt2800_hw_get_chippkg(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ return rt2800ops->hw_get_chippkg(); ++} ++ ++static inline int rt2800_hw_get_chipver(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ return rt2800ops->hw_get_chipver(); ++} ++ ++static inline int rt2800_hw_get_chipeco(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ return rt2800ops->hw_get_chipeco(); ++} ++ + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1); +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -289,6 +289,10 @@ static int rt2800pci_read_eeprom(struct + return retval; + } + ++static int rt2800pci_get_chippkg(void) { return 0; } ++static int rt2800pci_get_chipver(void) { return 0; } ++static int rt2800pci_get_chipeco(void) { return 0; } ++ + static const struct ieee80211_ops rt2800pci_mac80211_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, +@@ -336,6 +340,9 @@ static const struct rt2800_ops rt2800pci + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, + .drv_get_dma_done = rt2800mmio_get_dma_done, ++ .hw_get_chippkg = rt2800pci_get_chippkg, ++ .hw_get_chipver = rt2800pci_get_chipver, ++ .hw_get_chipeco = rt2800pci_get_chipeco, + }; + + static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -27,6 +27,12 @@ + #include "rt2800lib.h" + #include "rt2800mmio.h" + ++/* Needed to probe CHIP_VER register on MT7620 */ ++#ifdef CONFIG_SOC_MT7620 ++#include ++#include ++#endif ++ + /* Allow hardware encryption to be disabled. */ + static bool modparam_nohwcrypt; + module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444); +@@ -118,6 +124,27 @@ static int rt2800soc_write_firmware(stru + return 0; + } + ++#ifdef CONFIG_SOC_MT7620 ++static int rt2800soc_get_chippkg(void) ++{ ++ return mt7620_get_pkg(); ++} ++ ++static int rt2800soc_get_chipver(void) ++{ ++ return mt7620_get_chipver(); ++} ++ ++static int rt2800soc_get_chipeco(void) ++{ ++ return mt7620_get_eco(); ++} ++#else ++static int rt2800soc_get_chippkg(void) { return 0; } ++static int rt2800soc_get_chipver(void) { return 0; } ++static int rt2800soc_get_chipeco(void) { return 0; } ++#endif ++ + static const struct ieee80211_ops rt2800soc_mac80211_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, +@@ -165,6 +192,9 @@ static const struct rt2800_ops rt2800soc + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, + .drv_get_dma_done = rt2800mmio_get_dma_done, ++ .hw_get_chippkg = rt2800soc_get_chippkg, ++ .hw_get_chipver = rt2800soc_get_chipver, ++ .hw_get_chipeco = rt2800soc_get_chipeco, + }; + + static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -628,6 +628,10 @@ static int rt2800usb_probe_hw(struct rt2 + return 0; + } + ++static int rt2800usb_get_chippkg(void) { return 0; } ++static int rt2800usb_get_chipver(void) { return 0; } ++static int rt2800usb_get_chipeco(void) { return 0; } ++ + static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, +@@ -676,6 +680,9 @@ static const struct rt2800_ops rt2800usb + .drv_init_registers = rt2800usb_init_registers, + .drv_get_txwi = rt2800usb_get_txwi, + .drv_get_dma_done = rt2800usb_get_dma_done, ++ .hw_get_chippkg = rt2800usb_get_chippkg, ++ .hw_get_chipver = rt2800usb_get_chipver, ++ .hw_get_chipeco = rt2800usb_get_chipeco, + }; + + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { diff --git a/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch b/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch new file mode 100644 index 0000000..0b2e731 --- /dev/null +++ b/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch @@ -0,0 +1,437 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h +@@ -1056,6 +1056,11 @@ + #define MIMO_PS_CFG_RX_STBY_POL FIELD32(0x00000010) + #define MIMO_PS_CFG_RX_RX_STBY0 FIELD32(0x00000020) + ++#define BB_PA_MODE_CFG0 0x1214 ++#define BB_PA_MODE_CFG1 0x1218 ++#define RF_PA_MODE_CFG0 0x121C ++#define RF_PA_MODE_CFG1 0x1220 ++ + /* + * EDCA_AC0_CFG: + */ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -3842,14 +3842,16 @@ static void rt2800_config_channel_rf7620 + rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4); + rt2800_rfcsr_write(rt2x00dev, 19, rfcsr); + +- /* Default: XO=20MHz , SDM mode */ +- rfcsr = rt2800_rfcsr_read(rt2x00dev, 16); +- rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 4); +- rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); +- +- rfcsr = rt2800_rfcsr_read(rt2x00dev, 21); +- rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1); +- rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ /* Default: XO=20MHz , SDM mode */ ++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 16); ++ rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 4); ++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); ++ ++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 21); ++ rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1); ++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); ++ } + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620, +@@ -3883,18 +3885,23 @@ static void rt2800_config_channel_rf7620 + rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20); + } + +- if (conf_is_ht40(conf)) { +- rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08); +- rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08); +- } else { +- rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28); +- rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ if (conf_is_ht40(conf)) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08); ++ } else { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28); ++ } + } + +- rfcsr = rt2800_rfcsr_read(rt2x00dev, 28); +- rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40, +- conf_is_ht40(conf) && (rf->channel == 11)); +- rt2800_rfcsr_write(rt2x00dev, 28, rfcsr); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) == 2) { ++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 28); ++ rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40, ++ conf_is_ht40(conf) && (rf->channel == 11)); ++ rt2800_rfcsr_write(rt2x00dev, 28, rfcsr); ++ } + + if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) { + if (conf_is_ht40(conf)) { +@@ -4008,25 +4015,29 @@ static void rt2800_config_alc_rt6352(str + if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY))) + rt2x00_warn(rt2x00dev, "RF busy while configuring ALC\n"); + +- if (chan->center_freq > 2457) { +- bbp = rt2800_bbp_read(rt2x00dev, 30); +- bbp = 0x40; +- rt2800_bbp_write(rt2x00dev, 30, bbp); +- rt2800_rfcsr_write(rt2x00dev, 39, 0); +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) +- rt2800_rfcsr_write(rt2x00dev, 42, 0xfb); +- else +- rt2800_rfcsr_write(rt2x00dev, 42, 0x7b); +- } else { +- bbp = rt2800_bbp_read(rt2x00dev, 30); +- bbp = 0x1f; +- rt2800_bbp_write(rt2x00dev, 30, bbp); +- rt2800_rfcsr_write(rt2x00dev, 39, 0x80); +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) +- rt2800_rfcsr_write(rt2x00dev, 42, 0xdb); +- else +- rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ if (chan->center_freq > 2457) { ++ bbp = rt2800_bbp_read(rt2x00dev, 30); ++ bbp = 0x40; ++ rt2800_bbp_write(rt2x00dev, 30, bbp); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0); ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) ++ rt2800_rfcsr_write(rt2x00dev, 42, 0xfb); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x7b); ++ } else { ++ bbp = rt2800_bbp_read(rt2x00dev, 30); ++ bbp = 0x1f; ++ rt2800_bbp_write(rt2x00dev, 30, bbp); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) ++ rt2800_rfcsr_write(rt2x00dev, 42, 0xdb); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); ++ } + } ++ + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl); + + rt2800_vco_calibration(rt2x00dev); +@@ -4524,7 +4535,8 @@ static void rt2800_config_channel(struct + if (rt2x00_rt(rt2x00dev, RT6352)) { + /* BBP for GLRT BW */ + bbp = conf_is_ht40(conf) ? +- 0x10 : rt2x00_has_cap_external_lna_bg(rt2x00dev) ? ++ 0x10 : !rt2x00_has_cap_external_lna_bg(rt2x00dev) ? ++ 0x1a : rt2800_hw_get_chippkg(rt2x00dev) == 1 ? + 0x15 : 0x1a; + rt2800_bbp_glrt_write(rt2x00dev, 141, bbp); + +@@ -6042,18 +6054,34 @@ static int rt2800_init_registers(struct + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + } else if (rt2x00_rt(rt2x00dev, RT6352)) { +- rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401); +- rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001); +- rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +- rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000); +- rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); +- rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0); +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C); +- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C666C); +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, +- 0x3630363A); +- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT, +- 0x3630363A); ++ if (rt2800_hw_get_chipver(rt2x00dev) <= 1) { ++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, ++ 0x00000000); ++ rt2800_register_write(rt2x00dev, BB_PA_MODE_CFG0, ++ 0x000055FF); ++ rt2800_register_write(rt2x00dev, BB_PA_MODE_CFG1, ++ 0x00550055); ++ rt2800_register_write(rt2x00dev, RF_PA_MODE_CFG0, ++ 0x000055FF); ++ rt2800_register_write(rt2x00dev, RF_PA_MODE_CFG1, ++ 0x00550055); ++ } else { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); ++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150f0f); ++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x06060606); ++ rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); ++ rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, ++ 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, ++ 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, ++ 0x3630363A); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT, ++ 0x3630363A); ++ } + reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1); + rt2x00_set_field32(®, TX_ALC_CFG_1_ROS_BUSY_EN, 0); + rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg); +@@ -7160,14 +7188,16 @@ static void rt2800_init_bbp_6352(struct + rt2800_bbp_write(rt2x00dev, 188, 0x00); + rt2800_bbp_write(rt2x00dev, 189, 0x00); + +- rt2800_bbp_write(rt2x00dev, 91, 0x06); +- rt2800_bbp_write(rt2x00dev, 92, 0x04); +- rt2800_bbp_write(rt2x00dev, 93, 0x54); +- rt2800_bbp_write(rt2x00dev, 99, 0x50); +- rt2800_bbp_write(rt2x00dev, 148, 0x84); +- rt2800_bbp_write(rt2x00dev, 167, 0x80); +- rt2800_bbp_write(rt2x00dev, 178, 0xFF); +- rt2800_bbp_write(rt2x00dev, 106, 0x13); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_bbp_write(rt2x00dev, 91, 0x06); ++ rt2800_bbp_write(rt2x00dev, 92, 0x04); ++ rt2800_bbp_write(rt2x00dev, 93, 0x54); ++ rt2800_bbp_write(rt2x00dev, 99, 0x50); ++ rt2800_bbp_write(rt2x00dev, 148, 0x84); ++ rt2800_bbp_write(rt2x00dev, 167, 0x80); ++ rt2800_bbp_write(rt2x00dev, 178, 0xFF); ++ rt2800_bbp_write(rt2x00dev, 106, 0x13); ++ } + + /* BBP for G band GLRT function (BBP_128 ~ BBP_221) */ + rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00); +@@ -10398,6 +10428,9 @@ static void rt2800_restore_rf_bbp_rt6352 + rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0); + } + ++ if (rt2800_hw_get_chippkg(rt2x00dev) != 1) ++ return; ++ + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); + rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); +@@ -10479,6 +10512,9 @@ static void rt2800_calibration_rt6352_st + rt2800_register_write(rt2x00dev, RF_BYPASS3, reg); + } + ++ if (rt2800_hw_get_chippkg(rt2x00dev) != 1) ++ return; ++ + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66); + rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20); +@@ -10569,31 +10605,36 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rfcsr_write(rt2x00dev, 42, 0x5B); + rt2800_rfcsr_write(rt2x00dev, 43, 0x00); + +- rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +- if (rt2800_clk_is_20mhz(rt2x00dev)) +- rt2800_rfcsr_write(rt2x00dev, 13, 0x03); +- else +- rt2800_rfcsr_write(rt2x00dev, 13, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 14, 0x7C); +- rt2800_rfcsr_write(rt2x00dev, 16, 0x80); +- rt2800_rfcsr_write(rt2x00dev, 17, 0x99); +- rt2800_rfcsr_write(rt2x00dev, 18, 0x99); +- rt2800_rfcsr_write(rt2x00dev, 19, 0x09); +- rt2800_rfcsr_write(rt2x00dev, 20, 0x50); +- rt2800_rfcsr_write(rt2x00dev, 21, 0xB0); +- rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 23, 0x06); +- rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 25, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 26, 0x5D); +- rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 28, 0x61); +- rt2800_rfcsr_write(rt2x00dev, 29, 0xB5); +- rt2800_rfcsr_write(rt2x00dev, 43, 0x02); +- +- rt2800_rfcsr_write(rt2x00dev, 28, 0x62); +- rt2800_rfcsr_write(rt2x00dev, 29, 0xAD); +- rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x21); ++ if (rt2800_clk_is_20mhz(rt2x00dev)) ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x03); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x7C); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 17, 0x99); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x99); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x09); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0x50); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0xB0); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x06); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x5D); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x61); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xB5); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x02); ++ } ++ ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x62); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xAD); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ } + + /* Initialize RF channel register to default value */ + rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03); +@@ -10659,63 +10700,71 @@ static void rt2800_init_rfcsr_6352(struc + + rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5); + +- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); +- rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0x67); +- rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0x69); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF); +- rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27); +- rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x20); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0x67); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0x69); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); ++ } + +- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ } + +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); +- +- /* Initialize RF channel register for DRQFN */ +- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 0 && ++ rt2800_hw_get_chipver(rt2x00dev) == 1) { ++ /* Initialize RF channel register for DRQFN */ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); ++ } + + /* Initialize RF DC calibration register to default value */ + rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47); +@@ -10778,12 +10827,17 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00); + +- rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08); +- rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04); +- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20); ++ } + +- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); +- rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); ++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 && ++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); ++ } + } + + static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) diff --git a/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch new file mode 100644 index 0000000..23a4254 --- /dev/null +++ b/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Mon, 27 Oct 2014 00:00:00 +0100 +Subject: [PATCH] mac80211: preseve AP mode keys across STA reconnect + +Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnect +--- + net/mac80211/cfg.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1691,12 +1691,6 @@ static int ieee80211_stop_ap(struct wiph + + __sta_info_flush(sdata, true, link_id, NULL); + +- ieee80211_remove_link_keys(link, &keys); +- if (!list_empty(&keys)) { +- synchronize_net(); +- ieee80211_free_key_list(local, &keys); +- } +- + ieee80211_stop_mbssid(sdata); + RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL); + diff --git a/patches/subsys/120-cfg80211_allow_perm_addr_change.patch b/patches/subsys/120-cfg80211_allow_perm_addr_change.patch new file mode 100644 index 0000000..f315ae5 --- /dev/null +++ b/patches/subsys/120-cfg80211_allow_perm_addr_change.patch @@ -0,0 +1,52 @@ +From: Felix Fietkau +Date: Thu, 11 Dec 2014 00:00:00 +0100 +Subject: [PATCH] cfg80211: add support for changing the device mac address via + sysfs + +--- + net/wireless/sysfs.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +--- a/net/wireless/sysfs.c ++++ b/net/wireless/sysfs.c +@@ -24,18 +24,35 @@ static inline struct cfg80211_registered + return container_of(dev, struct cfg80211_registered_device, wiphy.dev); + } + +-#define SHOW_FMT(name, fmt, member) \ ++#define SHOW_FMT(name, fmt, member, mode) \ + static ssize_t name ## _show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ + } \ +-static DEVICE_ATTR_RO(name) ++static DEVICE_ATTR_##mode(name) + +-SHOW_FMT(index, "%d", wiphy_idx); +-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); +-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); ++static ssize_t macaddress_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') ++ return -EINVAL; ++ ++ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN); ++ ++ return strnlen(buf, len); ++} ++ ++SHOW_FMT(index, "%d", wiphy_idx, RO); ++SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW); ++SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO); + + static ssize_t name_show(struct device *dev, + struct device_attribute *attr, diff --git a/patches/subsys/130-disable_auto_vif.patch b/patches/subsys/130-disable_auto_vif.patch new file mode 100644 index 0000000..aec9a32 --- /dev/null +++ b/patches/subsys/130-disable_auto_vif.patch @@ -0,0 +1,27 @@ +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1595,24 +1595,6 @@ int ieee80211_register_hw(struct ieee802 + + ieee80211_check_wbrf_support(local); + +- rtnl_lock(); +- wiphy_lock(hw->wiphy); +- +- /* add one default STA interface if supported */ +- if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) && +- !ieee80211_hw_check(hw, NO_AUTO_VIF)) { +- struct vif_params params = {0}; +- +- result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL, +- NL80211_IFTYPE_STATION, ¶ms); +- if (result) +- wiphy_warn(local->hw.wiphy, +- "Failed to add default virtual iface\n"); +- } +- +- wiphy_unlock(hw->wiphy); +- rtnl_unlock(); +- + #ifdef CONFIG_INET + local->ifa_notifier.notifier_call = ieee80211_ifa_changed; + result = register_inetaddr_notifier(&local->ifa_notifier); diff --git a/patches/subsys/210-ap_scan.patch b/patches/subsys/210-ap_scan.patch new file mode 100644 index 0000000..1d56827 --- /dev/null +++ b/patches/subsys/210-ap_scan.patch @@ -0,0 +1,19 @@ +From: Felix Fietkau +Date: Wed, 3 Oct 2012 00:00:00 +0200 +Subject: [PATCH] mac80211: allow scans in access point mode (for site survey) + +--- + net/mac80211/cfg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2925,6 +2925,8 @@ static int ieee80211_scan(struct wiphy * + */ + fallthrough; + case NL80211_IFTYPE_AP: ++ /* skip check */ ++ break; + /* + * If the scan has been forced (and the driver supports + * forcing), don't care about being beaconing already. diff --git a/patches/subsys/220-allow-ibss-mixed.patch b/patches/subsys/220-allow-ibss-mixed.patch new file mode 100644 index 0000000..6ef7fb2 --- /dev/null +++ b/patches/subsys/220-allow-ibss-mixed.patch @@ -0,0 +1,40 @@ +From: Hauke Mehrtens +Date: Mon, 24 Feb 2020 00:00:00 +0100 +Subject: [PATCH] mac80211: Allow IBSS mode and different beacon intervals + +ath10k-ct supports the combination to select IBSS (ADHOC) mode and +different beacon intervals together. mac80211 does not like this +combination, but Ben says this is ok, so remove this check. + +ath10k-ct starting with version 5.2 allows the combination of +NL80211_IFTYPE_ADHOC and beacon_int_min_gcd in ath10k_10x_ct_if_comb +which triggers this warning. Ben told me that this is not a big problem +and we should ignore this. +--- + net/wireless/core.c | 15 --------------- + 1 file changed, 15 deletions(-) + +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -679,21 +679,6 @@ int wiphy_verify_iface_combinations(stru + c->limits[j].max > 1)) + return -EINVAL; + +- /* +- * This isn't well-defined right now. If you have an +- * IBSS interface, then its beacon interval may change +- * by joining other networks, and nothing prevents it +- * from doing that. +- * So technically we probably shouldn't even allow AP +- * and IBSS in the same interface, but it seems that +- * some drivers support that, possibly only with fixed +- * beacon intervals for IBSS. +- */ +- if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) && +- c->beacon_int_min_gcd)) { +- return -EINVAL; +- } +- + cnt += c->limits[j].max; + /* + * Don't advertise an unsupported type diff --git a/patches/subsys/230-avoid-crashing-missing-band.patch b/patches/subsys/230-avoid-crashing-missing-band.patch new file mode 100644 index 0000000..2de9bec --- /dev/null +++ b/patches/subsys/230-avoid-crashing-missing-band.patch @@ -0,0 +1,34 @@ +From: David Bauer +Date: Thu, 30 Nov 2023 07:32:52 +0100 +Subject: [PATCH] mac80211: avoid crashing on invalid band info + +Frequent crashes have been observed on MT7916 based platforms. While the +root of these crashes are currently unknown, they happen when decoding +rate information of connected STAs in AP mode. The rate-information is +associated with a band which is not available on the PHY. + +Check for this condition in order to avoid crashing the whole system. +This patch should be removed once the roout cause has been found and +fixed. + +Link: https://github.com/freifunk-gluon/gluon/issues/2980 + +Signed-off-by: David Bauer +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2468,6 +2468,13 @@ static void sta_stats_decode_rate(struct + + sband = local->hw.wiphy->bands[band]; + ++ if (!sband) { ++ wiphy_warn(local->hw.wiphy, ++ "Invalid band %d\n", ++ band); ++ break; ++ } ++ + if (WARN_ON_ONCE(!sband->bitrates)) + break; + diff --git a/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch new file mode 100644 index 0000000..86504c4 --- /dev/null +++ b/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch @@ -0,0 +1,38 @@ +From b478e06a16a8baa00c5ecc87c1d636981f2206d5 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 29 Oct 2019 10:25:25 +0100 +Subject: [PATCH] mac80211: sta: randomize BA session dialog token allocator + +We currently always start the dialog token generator at zero, +so the first dialog token we use is always 1. This would be +OK if we had a perfect guarantee that we always do a proper +deauth/re-auth handshake, but in IBSS mode this doesn't always +happen properly. + +To make problems with block ack (aggregation) sessions getting +stuck less likely, randomize the dialog token so if we start a +new session but the peer still has old state for us, it can +better detect this. + +This is really just a workaround to make things a bit more +robust than they are now - a better fix would be to do a full +authentication handshake in IBSS mode upon having discovered a +new station, and on the receiver resetting the state (removing +and re-adding the station) on receiving the authentication +packet. + +Signed-off-by: Johannes Berg +--- + net/mac80211/sta_info.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -582,6 +582,7 @@ __sta_info_alloc(struct ieee80211_sub_if + spin_lock_init(&sta->ps_lock); + INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); + wiphy_work_init(&sta->ampdu_mlme.work, ieee80211_ba_session_work); ++ sta->ampdu_mlme.dialog_token_allocator = get_random_u32_below(U8_MAX); + #ifdef CPTCFG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sdata->vif)) { + sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); diff --git a/patches/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch b/patches/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch new file mode 100644 index 0000000..0d475b7 --- /dev/null +++ b/patches/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch @@ -0,0 +1,21 @@ +From: Felix Fietkau +Date: Wed, 28 Apr 2021 21:03:13 +0200 +Subject: [PATCH] mac80211: minstrel_ht: fix MINSTREL_FRAC macro + +Add missing braces to avoid issues with e.g. using additions in the +div expression + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.h ++++ b/net/mac80211/rc80211_minstrel_ht.h +@@ -14,7 +14,7 @@ + + /* scaled fraction values */ + #define MINSTREL_SCALE 12 +-#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) ++#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / (div)) + #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) + + #define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */ diff --git a/patches/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch b/patches/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch new file mode 100644 index 0000000..f26477e --- /dev/null +++ b/patches/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch @@ -0,0 +1,30 @@ +From: Felix Fietkau +Date: Sat, 6 Feb 2021 16:08:01 +0100 +Subject: [PATCH] mac80211: minstrel_ht: reduce fluctuations in rate + probability stats + +In some scenarios when there is a lot of fluctuation in packet error rates, +rate switching can be amplified when the statistics get skewed by time slots +with very few tries. +Make the input data to the moving average more smooth by adding the +success/attempts count from the last stats window as well. This has the +advantage of smoothing the data without introducing any extra lag to sampling +rates. +This significantly improves rate stability on a strong test link subjected to +periodic noise bursts generated with a SDR + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -769,7 +769,8 @@ minstrel_ht_calc_rate_stats(struct minst + unsigned int cur_prob; + + if (unlikely(mrs->attempts > 0)) { +- cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); ++ cur_prob = MINSTREL_FRAC(mrs->success + mrs->last_success, ++ mrs->attempts + mrs->last_attempts); + minstrel_filter_avg_add(&mrs->prob_avg, + &mrs->prob_avg_1, cur_prob); + mrs->att_hist += mrs->attempts; diff --git a/patches/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch b/patches/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch new file mode 100644 index 0000000..9b3cc3a --- /dev/null +++ b/patches/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch @@ -0,0 +1,151 @@ +From: Felix Fietkau +Date: Sat, 6 Feb 2021 16:33:14 +0100 +Subject: [PATCH] mac80211: minstrel_ht: rework rate downgrade code and + max_prob rate selection + +The current fallback code for fast rate switching on potentially failing rates +is triggering too often if there is some strong noise on the channel. This can +lead to wild fluctuations in the rate selection. +Additionally, switching down to max_prob_rate can create a significant gap down +in throughput, especially when using only 2 spatial streams, because max_prob_rate +is limited to using fewer streams than the max_tp rates. +In order to improve throughput without reducing reliability too much, use the +rate downgrade code for the max_prob_rate only, and allow the non-downgraded +max_prob_rate to use as many spatial streams as the max_tp rates + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -580,6 +580,14 @@ minstrel_ht_set_best_prob_rate(struct mi + int cur_tp_avg, cur_group, cur_idx; + int max_gpr_group, max_gpr_idx; + int max_gpr_tp_avg, max_gpr_prob; ++ int min_dur; ++ ++ min_dur = max(minstrel_get_duration(mi->max_tp_rate[0]), ++ minstrel_get_duration(mi->max_tp_rate[1])); ++ ++ /* make the rate at least 18% slower than max tp rates */ ++ if (minstrel_get_duration(index) <= min_dur * 19 / 16) ++ return; + + cur_group = MI_RATE_GROUP(index); + cur_idx = MI_RATE_IDX(index); +@@ -601,11 +609,6 @@ minstrel_ht_set_best_prob_rate(struct mi + !minstrel_ht_is_legacy_group(max_tp_group)) + return; + +- /* skip rates faster than max tp rate with lower prob */ +- if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) && +- mrs->prob_avg < max_tp_prob) +- return; +- + max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate); + max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate); + max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; +@@ -663,40 +666,6 @@ minstrel_ht_assign_best_tp_rates(struct + + } + +-/* +- * Try to increase robustness of max_prob rate by decrease number of +- * streams if possible. +- */ +-static inline void +-minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) +-{ +- struct minstrel_mcs_group_data *mg; +- int tmp_max_streams, group, tmp_idx, tmp_prob; +- int tmp_tp = 0; +- +- if (!mi->sta->deflink.ht_cap.ht_supported) +- return; +- +- group = MI_RATE_GROUP(mi->max_tp_rate[0]); +- tmp_max_streams = minstrel_mcs_groups[group].streams; +- for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { +- mg = &mi->groups[group]; +- if (!mi->supported[group] || group == MINSTREL_CCK_GROUP) +- continue; +- +- tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate); +- tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg; +- +- if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) && +- (minstrel_mcs_groups[group].streams < tmp_max_streams)) { +- mi->max_prob_rate = mg->max_group_prob_rate; +- tmp_tp = minstrel_ht_get_tp_avg(mi, group, +- tmp_idx, +- tmp_prob); +- } +- } +-} +- + static u16 + __minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi, + enum minstrel_sample_type type) +@@ -1176,8 +1145,6 @@ minstrel_ht_update_stats(struct minstrel + + mi->max_prob_rate = tmp_max_prob_rate; + +- /* Try to increase robustness of max_prob_rate*/ +- minstrel_ht_prob_rate_reduce_streams(mi); + minstrel_ht_refill_sample_rates(mi); + + #ifdef CPTCFG_MAC80211_DEBUGFS +@@ -1256,7 +1223,7 @@ minstrel_ht_ri_txstat_valid(struct minst + } + + static void +-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary) ++minstrel_downgrade_prob_rate(struct minstrel_ht_sta *mi, u16 *idx) + { + int group, orig_group; + +@@ -1271,11 +1238,7 @@ minstrel_downgrade_rate(struct minstrel_ + minstrel_mcs_groups[orig_group].streams) + continue; + +- if (primary) +- *idx = mi->groups[group].max_group_tp_rate[0]; +- else +- *idx = mi->groups[group].max_group_tp_rate[1]; +- break; ++ *idx = mi->groups[group].max_group_prob_rate; + } + } + +@@ -1286,7 +1249,7 @@ minstrel_ht_tx_status(void *priv, struct + struct ieee80211_tx_info *info = st->info; + struct minstrel_ht_sta *mi = priv_sta; + struct ieee80211_tx_rate *ar = info->status.rates; +- struct minstrel_rate_stats *rate, *rate2; ++ struct minstrel_rate_stats *rate; + struct minstrel_priv *mp = priv; + u32 update_interval = mp->update_interval; + bool last, update = false; +@@ -1354,18 +1317,13 @@ minstrel_ht_tx_status(void *priv, struct + /* + * check for sudden death of spatial multiplexing, + * downgrade to a lower number of streams if necessary. ++ * only do this for the max_prob_rate to prevent spurious ++ * rate fluctuations when the link changes suddenly + */ +- rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); ++ rate = minstrel_get_ratestats(mi, mi->max_prob_rate); + if (rate->attempts > 30 && + rate->success < rate->attempts / 4) { +- minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); +- update = true; +- } +- +- rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); +- if (rate2->attempts > 30 && +- rate2->success < rate2->attempts / 4) { +- minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); ++ minstrel_downgrade_prob_rate(mi, &mi->max_prob_rate); + update = true; + } + } diff --git a/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch b/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch new file mode 100644 index 0000000..17e2151 --- /dev/null +++ b/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch @@ -0,0 +1,53 @@ +From: Felix Fietkau +Date: Sun, 26 Jun 2022 11:43:25 +0200 +Subject: [PATCH] mac80211: increase quantum for airtime scheduler + +Given the typical AQL budget and queue length, a quantum of 256 with the +default station weight often requires iterating over all queues frequently, +until one of them becomes eligible. +Improve performance by using 8 times station weight as scheduler quantum + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -103,6 +103,8 @@ ieee80211_sta_keep_active(struct sta_inf + return time_before_eq(jiffies, sta->airtime[ac].last_active + HZ / 10); + } + ++#define AIRTIME_QUANTUM_SHIFT 3 ++ + struct ieee80211_bss { + u32 device_ts_beacon, device_ts_presp; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4066,7 +4066,7 @@ struct ieee80211_txq *ieee80211_next_txq + + if (deficit < 0) + sta->airtime[txqi->txq.ac].deficit += +- sta->airtime_weight; ++ sta->airtime_weight << AIRTIME_QUANTUM_SHIFT; + + if (deficit < 0 || !aql_check) { + list_move_tail(&txqi->schedule_order, +@@ -4209,7 +4209,8 @@ bool ieee80211_txq_may_transmit(struct i + } + sta = container_of(iter->txq.sta, struct sta_info, sta); + if (ieee80211_sta_deficit(sta, ac) < 0) +- sta->airtime[ac].deficit += sta->airtime_weight; ++ sta->airtime[ac].deficit += sta->airtime_weight << ++ AIRTIME_QUANTUM_SHIFT; + list_move_tail(&iter->schedule_order, &local->active_txqs[ac]); + } + +@@ -4217,7 +4218,7 @@ bool ieee80211_txq_may_transmit(struct i + if (sta->airtime[ac].deficit >= 0) + goto out; + +- sta->airtime[ac].deficit += sta->airtime_weight; ++ sta->airtime[ac].deficit += sta->airtime_weight << AIRTIME_QUANTUM_SHIFT; + list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]); + spin_unlock_bh(&local->active_txq_lock[ac]); + diff --git a/patches/subsys/310-cfg80211-allow-grace-period-for-DFS-available-after-.patch b/patches/subsys/310-cfg80211-allow-grace-period-for-DFS-available-after-.patch new file mode 100644 index 0000000..8197b06 --- /dev/null +++ b/patches/subsys/310-cfg80211-allow-grace-period-for-DFS-available-after-.patch @@ -0,0 +1,153 @@ +From: Felix Fietkau +Date: Thu, 14 Sep 2023 13:17:16 +0200 +Subject: [PATCH] cfg80211: allow grace period for DFS available after beacon + shutdown + +Fixes reconfiguring an AP on a DFS channel in non-ETSI regdomain + +Fixes: b35a51c7dd25 ("cfg80211: Make pre-CAC results valid only for ETSI domain") +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -190,6 +190,8 @@ enum ieee80211_channel_flags { + * @dfs_state: current state of this channel. Only relevant if radar is required + * on this channel. + * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. ++ * @dfs_state_last_available: timestamp (jiffies) of the last time when the ++ * channel was available. + * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels. + * @psd: power spectral density (in dBm) + */ +@@ -207,6 +209,7 @@ struct ieee80211_channel { + int orig_mag, orig_mpwr; + enum nl80211_dfs_state dfs_state; + unsigned long dfs_state_entered; ++ unsigned long dfs_state_last_available; + unsigned int dfs_cac_ms; + s8 psd; + }; +--- a/net/wireless/ap.c ++++ b/net/wireless/ap.c +@@ -30,6 +30,9 @@ static int ___cfg80211_stop_ap(struct cf + if (!wdev->links[link_id].ap.beacon_interval) + return -ENOENT; + ++ cfg80211_update_last_available(wdev->wiphy, ++ &wdev->links[link_id].ap.chandef); ++ + err = rdev_stop_ap(rdev, dev, link_id); + if (!err) { + wdev->conn_owner_nlportid = 0; +@@ -41,9 +44,6 @@ static int ___cfg80211_stop_ap(struct cf + if (notify) + nl80211_send_ap_stopped(wdev, link_id); + +- /* Should we apply the grace period during beaconing interface +- * shutdown also? +- */ + cfg80211_sched_dfs_chan_update(rdev); + } + +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -643,6 +643,8 @@ void cfg80211_set_dfs_state(struct wiphy + + c->dfs_state = dfs_state; + c->dfs_state_entered = jiffies; ++ if (dfs_state == NL80211_DFS_AVAILABLE) ++ c->dfs_state_last_available = jiffies; + } + } + +@@ -990,6 +992,53 @@ bool cfg80211_any_wiphy_oper_chan(struct + return false; + } + ++static void ++__cfg80211_update_last_available(struct wiphy *wiphy, ++ u32 center_freq, ++ u32 bandwidth) ++{ ++ struct ieee80211_channel *c; ++ u32 freq, start_freq, end_freq; ++ ++ if (bandwidth <= MHZ_TO_KHZ(20)) ++ start_freq = end_freq = center_freq; ++ else { ++ start_freq = center_freq - bandwidth / 2 + MHZ_TO_KHZ(10); ++ end_freq = center_freq + bandwidth / 2 - MHZ_TO_KHZ(10); ++ } ++ ++ /* ++ * Check entire range of channels for the bandwidth. ++ * If any channel in between is disabled or has not ++ * had gone through CAC return false ++ */ ++ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { ++ c = ieee80211_get_channel_khz(wiphy, freq); ++ if (!c) ++ return; ++ ++ c->dfs_state_last_available = jiffies; ++ } ++} ++ ++void cfg80211_update_last_available(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef) ++{ ++ int width; ++ ++ width = cfg80211_chandef_get_width(chandef); ++ if (width < 0) ++ return; ++ ++ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1), ++ width); ++ if (chandef->width != NL80211_CHAN_WIDTH_80P80) ++ return; ++ ++ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2), ++ width); ++} ++ + static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef) + { +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -474,6 +474,8 @@ void cfg80211_set_dfs_state(struct wiphy + enum nl80211_dfs_state dfs_state); + + void cfg80211_dfs_channels_update_work(struct work_struct *work); ++void cfg80211_update_last_available(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef); + + void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); + +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -1038,6 +1038,8 @@ void cfg80211_dfs_channels_update_work(s + if (c->dfs_state == NL80211_DFS_UNAVAILABLE) { + time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS; + radar_event = NL80211_RADAR_NOP_FINISHED; ++ timeout = c->dfs_state_entered + ++ msecs_to_jiffies(time_dfs_update); + } else { + if (regulatory_pre_cac_allowed(wiphy) || + cfg80211_any_wiphy_oper_chan(wiphy, c)) +@@ -1045,11 +1047,10 @@ void cfg80211_dfs_channels_update_work(s + + time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS; + radar_event = NL80211_RADAR_PRE_CAC_EXPIRED; ++ timeout = c->dfs_state_last_available + ++ msecs_to_jiffies(time_dfs_update); + } + +- timeout = c->dfs_state_entered + +- msecs_to_jiffies(time_dfs_update); +- + if (time_after_eq(jiffies, timeout)) { + c->dfs_state = NL80211_DFS_USABLE; + c->dfs_state_entered = jiffies; diff --git a/patches/subsys/320-mac80211-add-AQL-support-for-broadcast-packets.patch b/patches/subsys/320-mac80211-add-AQL-support-for-broadcast-packets.patch new file mode 100644 index 0000000..f8751b3 --- /dev/null +++ b/patches/subsys/320-mac80211-add-AQL-support-for-broadcast-packets.patch @@ -0,0 +1,293 @@ +From: Felix Fietkau +Date: Fri, 9 Feb 2024 19:43:40 +0100 +Subject: [PATCH] mac80211: add AQL support for broadcast packets + +Excessive broadcast traffic with little competing unicast traffic can easily +flood hardware queues, leading to throughput issues. Additionally, filling +the hardware queues with too many packets breaks FQ for broadcast data. +Fix this by enabling AQL for broadcast packets. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -3437,6 +3437,7 @@ enum wiphy_params_flags { + /* The per TXQ device queue limit in airtime */ + #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000 + #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000 ++#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000 + + /* The per interface airtime threshold to switch to lower queue limit */ + #define IEEE80211_AQL_THRESHOLD 24000 +--- a/net/mac80211/debugfs.c ++++ b/net/mac80211/debugfs.c +@@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct f + "VI %u us\n" + "BE %u us\n" + "BK %u us\n" ++ "BC/MC %u us\n" + "total %u us\n", + atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]), + atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]), + atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]), + atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]), ++ atomic_read(&local->aql_bc_pending_airtime), + atomic_read(&local->aql_total_pending_airtime)); + return simple_read_from_buffer(user_buf, count, ppos, + buf, len); +@@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct + "VO %u %u\n" + "VI %u %u\n" + "BE %u %u\n" +- "BK %u %u\n", ++ "BK %u %u\n" ++ "BC/MC %u\n", + local->aql_txq_limit_low[IEEE80211_AC_VO], + local->aql_txq_limit_high[IEEE80211_AC_VO], + local->aql_txq_limit_low[IEEE80211_AC_VI], +@@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct + local->aql_txq_limit_low[IEEE80211_AC_BE], + local->aql_txq_limit_high[IEEE80211_AC_BE], + local->aql_txq_limit_low[IEEE80211_AC_BK], +- local->aql_txq_limit_high[IEEE80211_AC_BK]); ++ local->aql_txq_limit_high[IEEE80211_AC_BK], ++ local->aql_txq_limit_bc); + return simple_read_from_buffer(user_buf, count, ppos, + buf, len); + } +@@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struc + else + buf[count] = '\0'; + ++ if (sscanf(buf, "mcast %u", &q_limit_low) == 1) { ++ local->aql_txq_limit_bc = q_limit_low; ++ return count; ++ } ++ + if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3) + return -EINVAL; + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1377,10 +1377,12 @@ struct ieee80211_local { + spinlock_t handle_wake_tx_queue_lock; + + u16 airtime_flags; ++ u32 aql_txq_limit_bc; + u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; + u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; + u32 aql_threshold; + atomic_t aql_total_pending_airtime; ++ atomic_t aql_bc_pending_airtime; + atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS]; + + const struct ieee80211_ops *ops; +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -959,6 +959,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + spin_lock_init(&local->rx_path_lock); + spin_lock_init(&local->queue_stop_reason_lock); + ++ local->aql_txq_limit_bc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC; + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + INIT_LIST_HEAD(&local->active_txqs[i]); + spin_lock_init(&local->active_txq_lock[i]); +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2382,13 +2382,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre + + void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, + struct sta_info *sta, u8 ac, +- u16 tx_airtime, bool tx_completed) ++ u16 tx_airtime, bool tx_completed, ++ bool mcast) + { + int tx_pending; + + if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) + return; + ++ if (mcast) { ++ if (!tx_completed) { ++ atomic_add(tx_airtime, &local->aql_bc_pending_airtime); ++ return; ++ } ++ ++ tx_pending = atomic_sub_return(tx_airtime, ++ &local->aql_bc_pending_airtime); ++ if (tx_pending < 0) ++ atomic_cmpxchg(&local->aql_bc_pending_airtime, ++ tx_pending, 0); ++ return; ++ } ++ + if (!tx_completed) { + if (sta) + atomic_add(tx_airtime, +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2539,7 +2539,7 @@ static u16 ieee80211_store_ack_skb(struc + + spin_lock_irqsave(&local->ack_status_lock, flags); + id = idr_alloc(&local->ack_status_frames, ack_skb, +- 1, 0x2000, GFP_ATOMIC); ++ 1, 0x1000, GFP_ATOMIC); + spin_unlock_irqrestore(&local->ack_status_lock, flags); + + if (id >= 0) { +@@ -3967,20 +3967,20 @@ begin: + encap_out: + info->control.vif = vif; + +- if (tx.sta && +- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { +- bool ampdu = txq->ac != IEEE80211_AC_VO; ++ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { ++ bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO; + u32 airtime; + + airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, + skb->len, ampdu); +- if (airtime) { +- airtime = ieee80211_info_set_tx_time_est(info, airtime); +- ieee80211_sta_update_pending_airtime(local, tx.sta, +- txq->ac, +- airtime, +- false); +- } ++ if (!airtime) ++ return skb; ++ ++ airtime = ieee80211_info_set_tx_time_est(info, airtime); ++ info->tx_time_mc = !tx.sta; ++ ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac, ++ airtime, false, ++ info->tx_time_mc); + } + + return skb; +@@ -4032,6 +4032,7 @@ struct ieee80211_txq *ieee80211_next_txq + struct ieee80211_txq *ret = NULL; + struct txq_info *txqi = NULL, *head = NULL; + bool found_eligible_txq = false; ++ bool aql_check; + + spin_lock_bh(&local->active_txq_lock[ac]); + +@@ -4055,26 +4056,26 @@ struct ieee80211_txq *ieee80211_next_txq + if (!head) + head = txqi; + ++ aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); ++ if (aql_check) ++ found_eligible_txq = true; ++ + if (txqi->txq.sta) { + struct sta_info *sta = container_of(txqi->txq.sta, + struct sta_info, sta); +- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); +- s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac); +- +- if (aql_check) +- found_eligible_txq = true; +- +- if (deficit < 0) ++ if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) { + sta->airtime[txqi->txq.ac].deficit += + sta->airtime_weight << AIRTIME_QUANTUM_SHIFT; +- +- if (deficit < 0 || !aql_check) { +- list_move_tail(&txqi->schedule_order, +- &local->active_txqs[txqi->txq.ac]); +- goto begin; ++ aql_check = false; + } + } + ++ if (!aql_check) { ++ list_move_tail(&txqi->schedule_order, ++ &local->active_txqs[txqi->txq.ac]); ++ goto begin; ++ } ++ + if (txqi->schedule_round == local->schedule_round[ac]) + goto out; + +@@ -4139,7 +4140,8 @@ bool ieee80211_txq_airtime_check(struct + return true; + + if (!txq->sta) +- return true; ++ return atomic_read(&local->aql_bc_pending_airtime) < ++ local->aql_txq_limit_bc; + + if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) + return true; +@@ -4188,15 +4190,15 @@ bool ieee80211_txq_may_transmit(struct i + + spin_lock_bh(&local->active_txq_lock[ac]); + +- if (!txqi->txq.sta) +- goto out; +- + if (list_empty(&txqi->schedule_order)) + goto out; + + if (!ieee80211_txq_schedule_airtime_check(local, ac)) + goto out; + ++ if (!txqi->txq.sta) ++ goto out; ++ + list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac], + schedule_order) { + if (iter == txqi) +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1245,8 +1245,8 @@ struct ieee80211_tx_info { + status_data_idr:1, + status_data:13, + hw_queue:4, ++ tx_time_mc:1, + tx_time_est:10; +- /* 1 free bit */ + + union { + struct { +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -147,7 +147,8 @@ struct airtime_info { + + void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, + struct sta_info *sta, u8 ac, +- u16 tx_airtime, bool tx_completed); ++ u16 tx_airtime, bool tx_completed, ++ bool mcast); + + struct sta_info; + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -734,7 +734,7 @@ static void ieee80211_report_used_skb(st + ieee80211_sta_update_pending_airtime(local, sta, + skb_get_queue_mapping(skb), + tx_time_est, +- true); ++ true, info->tx_time_mc); + rcu_read_unlock(); + } + +@@ -1143,10 +1143,11 @@ void ieee80211_tx_status_ext(struct ieee + /* Do this here to avoid the expensive lookup of the sta + * in ieee80211_report_used_skb(). + */ ++ bool mcast = IEEE80211_SKB_CB(skb)->tx_time_mc; + ieee80211_sta_update_pending_airtime(local, sta, + skb_get_queue_mapping(skb), + tx_time_est, +- true); ++ true, mcast); + ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0); + } + diff --git a/patches/subsys/330-wifi-mac80211-Do-not-schedule-stopped-TXQs.patch b/patches/subsys/330-wifi-mac80211-Do-not-schedule-stopped-TXQs.patch new file mode 100644 index 0000000..7824065 --- /dev/null +++ b/patches/subsys/330-wifi-mac80211-Do-not-schedule-stopped-TXQs.patch @@ -0,0 +1,36 @@ +From: Alexander Wetzel +Date: Thu, 17 Jul 2025 18:25:46 +0200 +Subject: [PATCH] wifi: mac80211: Do not schedule stopped TXQs + +Ignore TXQs with the flag IEEE80211_TXQ_STOP when scheduling a queue. + +The flag is only set after all fragments have been dequeued and won't +allow dequeueing other frames as long as the flag is set. + +For drivers using ieee80211_txq_schedule_start() this prevents an +loop trying to push the queued frames while IEEE80211_TXQ_STOP is set: + +After setting IEEE80211_TXQ_STOP the driver will call +ieee80211_return_txq(). Which calls __ieee80211_schedule_txq(), detects +that there sill are frames in the queue and immediately restarts the +stopped TXQ. Which can't dequeue any frame and thus starts over the loop. + +Signed-off-by: Alexander Wetzel +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Link: https://patch.msgid.link/20250717162547.94582-2-Alexander@wetzel-home.de +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4099,7 +4099,9 @@ void __ieee80211_schedule_txq(struct iee + + spin_lock_bh(&local->active_txq_lock[txq->ac]); + +- has_queue = force || txq_has_queue(txq); ++ has_queue = force || ++ (!test_bit(IEEE80211_TXQ_STOP, &txqi->flags) && ++ txq_has_queue(txq)); + if (list_empty(&txqi->schedule_order) && + (has_queue || ieee80211_txq_keep_active(txqi))) { + /* If airtime accounting is active, always enqueue STAs at the diff --git a/patches/subsys/331-wifi-mac80211-Don-t-call-fq_flow_idx-for-management-.patch b/patches/subsys/331-wifi-mac80211-Don-t-call-fq_flow_idx-for-management-.patch new file mode 100644 index 0000000..b33bf5c --- /dev/null +++ b/patches/subsys/331-wifi-mac80211-Don-t-call-fq_flow_idx-for-management-.patch @@ -0,0 +1,33 @@ +From: Alexander Wetzel +Date: Thu, 17 Jul 2025 18:25:47 +0200 +Subject: [PATCH] wifi: mac80211: Don't call fq_flow_idx() for management + frames + +skb_get_hash() can only be used when the skb is linked to a netdev +device. + +Signed-off-by: Alexander Wetzel +Fixes: 73bc9e0af594 ("mac80211: don't apply flow control on management frames") +Link: https://patch.msgid.link/20250717162547.94582-3-Alexander@wetzel-home.de +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1428,7 +1428,7 @@ static void ieee80211_txq_enqueue(struct + { + struct fq *fq = &local->fq; + struct fq_tin *tin = &txqi->tin; +- u32 flow_idx = fq_flow_idx(fq, skb); ++ u32 flow_idx; + + ieee80211_set_skb_enqueue_time(skb); + +@@ -1444,6 +1444,7 @@ static void ieee80211_txq_enqueue(struct + IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + __skb_queue_tail(&txqi->frags, skb); + } else { ++ flow_idx = fq_flow_idx(fq, skb); + fq_tin_enqueue(fq, tin, flow_idx, skb, + fq_skb_free_func); + } diff --git a/patches/subsys/332-wifi-mac80211-Check-802.11-encaps-offloading-in-ieee.patch b/patches/subsys/332-wifi-mac80211-Check-802.11-encaps-offloading-in-ieee.patch new file mode 100644 index 0000000..8ff0982 --- /dev/null +++ b/patches/subsys/332-wifi-mac80211-Check-802.11-encaps-offloading-in-ieee.patch @@ -0,0 +1,32 @@ +From: Remi Pommarel +Date: Thu, 17 Jul 2025 17:45:28 +0200 +Subject: [PATCH] wifi: mac80211: Check 802.11 encaps offloading in + ieee80211_tx_h_select_key() + +With 802.11 encapsulation offloading, ieee80211_tx_h_select_key() is +called on 802.3 frames. In that case do not try to use skb data as +valid 802.11 headers. + +Reported-by: Bert Karwatzki +Closes: https://lore.kernel.org/linux-wireless/20250410215527.3001-1-spasswolf@web.de +Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue") +Signed-off-by: Remi Pommarel +Link: https://patch.msgid.link/1af4b5b903a5fca5ebe67333d5854f93b2be5abe.1752765971.git.repk@triplefau.lt +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -612,6 +612,12 @@ ieee80211_tx_h_select_key(struct ieee802 + else + tx->key = NULL; + ++ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { ++ if (tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ++ info->control.hw_key = &tx->key->conf; ++ return TX_CONTINUE; ++ } ++ + if (tx->key) { + bool skip_hw = false; + diff --git a/patches/subsys/333-Reapply-wifi-mac80211-Update-skb-s-control-block-key.patch b/patches/subsys/333-Reapply-wifi-mac80211-Update-skb-s-control-block-key.patch new file mode 100644 index 0000000..5ef6d25 --- /dev/null +++ b/patches/subsys/333-Reapply-wifi-mac80211-Update-skb-s-control-block-key.patch @@ -0,0 +1,27 @@ +From: Remi Pommarel +Date: Thu, 17 Jul 2025 17:45:29 +0200 +Subject: [PATCH] Reapply "wifi: mac80211: Update skb's control block key in + ieee80211_tx_dequeue()" + +This reverts commit 0937cb5f345c ("Revert "wifi: mac80211: Update +skb's control block key in ieee80211_tx_dequeue()""). + +This commit broke TX with 802.11 encapsulation HW offloading, now that +this is fixed, reapply it. + +Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue") +Signed-off-by: Remi Pommarel +Link: https://patch.msgid.link/66b8fc39fb0194fa06c9ca7eeb6ffe0118dcb3ec.1752765971.git.repk@triplefau.lt +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3883,6 +3883,7 @@ begin: + * The key can be removed while the packet was queued, so need to call + * this here to get the current key. + */ ++ info->control.hw_key = NULL; + r = ieee80211_tx_h_select_key(&tx); + if (r != TX_CONTINUE) { + ieee80211_free_txskb(&local->hw, skb); diff --git a/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch b/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch new file mode 100644 index 0000000..1c3bb78 --- /dev/null +++ b/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch @@ -0,0 +1,44 @@ +From: Maharaja Kennadyrajan +Date: Fri, 18 Jul 2025 11:38:35 +0530 +Subject: [PATCH] wifi: mac80211: Add link iteration macro for link data + with rcu_dereference + +Currently, the existing macro for_each_link_data() uses sdata_dereference() +which requires the wiphy lock. This lock cannot be used in atomic or RCU +read-side contexts, such as in the RX path. + +Introduce a new macro, for_each_link_data_rcu(), that iterates over link of +sdata using rcu_dereference(), making it safe to use in RCU contexts. This +allows callers to access link data without requiring the wiphy lock. + +The macro takes into account the vif.valid_links bitmap and ensures only +valid links are accessed safely. Callers are responsible for ensuring that +rcu_read_lock() is held when using this macro. + +Signed-off-by: Maharaja Kennadyrajan +Link: https://patch.msgid.link/20250718060837.59371-3-maharaja.kennadyrajan@oss.qualcomm.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1237,6 +1237,19 @@ struct ieee80211_sub_if_data *vif_to_sda + ((__link) = sdata_dereference((__sdata)->link[__link_id], \ + (__sdata)))) + ++/* ++ * for_each_link_data_rcu should be used under RCU read lock. ++ */ ++#define for_each_link_data_rcu(sdata, __link) \ ++ /* outer loop just to define the variable ... */ \ ++ for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata; \ ++ __sdata = NULL /* always stop */) \ ++ for (int __link_id = 0; \ ++ __link_id < ARRAY_SIZE((__sdata)->link); __link_id++) \ ++ if ((!(__sdata)->vif.valid_links || \ ++ (__sdata)->vif.valid_links & BIT(__link_id)) && \ ++ ((__link) = rcu_dereference((__sdata)->link[__link_id]))) \ ++ + static inline int + ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, + struct cfg80211_rnr_elems *rnr_elems, diff --git a/patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch b/patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch new file mode 100644 index 0000000..f0226fd --- /dev/null +++ b/patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch @@ -0,0 +1,85 @@ +From: Maharaja Kennadyrajan +Date: Fri, 18 Jul 2025 11:38:36 +0530 +Subject: [PATCH] wifi: mac80211: extend beacon monitoring for MLO + +Currently, reset beacon monitor (ieee80211_sta_reset_beacon_monitor()) +timer is handled only for non-AP non-MLD STA and do not support non-AP MLD +STA. When the beacon loss occurs in non-AP MLD STA with the current +implementation, it is treated as a single link and the timer will reset +based on the timeout of the deflink, without checking all the links. + +Check the CSA flags for all the links in the MLO and decide whether to +schedule the work queue for beacon loss. If any of the links has CSA +active, then beacon loss work is not scheduled. + +Also, call the functions ieee80211_sta_reset_beacon_monitor() and +ieee80211_sta_reset_conn_monitor() from ieee80211_csa_switch_work() only +when all the links are CSA active. + +Signed-off-by: Maharaja Kennadyrajan +Link: https://patch.msgid.link/20250718060837.59371-4-maharaja.kennadyrajan@oss.qualcomm.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2439,6 +2439,21 @@ static void ieee80211_csa_switch_work(st + } + } + ++ /* ++ * It is not necessary to reset these timers if any link does not ++ * have an active CSA and that link still receives the beacons ++ * when other links have active CSA. ++ */ ++ for_each_link_data(sdata, link) { ++ if (!link->conf->csa_active) ++ return; ++ } ++ ++ /* ++ * Reset the beacon monitor and connection monitor timers when CSA ++ * is active for all links in MLO when channel switch occurs in all ++ * the links. ++ */ + ieee80211_sta_reset_beacon_monitor(sdata); + ieee80211_sta_reset_conn_monitor(sdata); + } +@@ -8389,16 +8404,32 @@ void ieee80211_sta_work(struct ieee80211 + } + } + ++static bool ++ieee80211_is_csa_in_progress(struct ieee80211_sub_if_data *sdata) ++{ ++ /* ++ * In MLO, check the CSA flags 'active' and 'waiting_bcn' for all ++ * the links. ++ */ ++ struct ieee80211_link_data *link; ++ ++ guard(rcu)(); ++ ++ for_each_link_data_rcu(sdata, link) { ++ if (!(link->conf->csa_active && ++ !link->u.mgd.csa.waiting_bcn)) ++ return false; ++ } ++ ++ return true; ++} ++ + static void ieee80211_sta_bcn_mon_timer(struct timer_list *t) + { + struct ieee80211_sub_if_data *sdata = + timer_container_of(sdata, t, u.mgd.bcn_mon_timer); + +- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- +- if (sdata->vif.bss_conf.csa_active && +- !sdata->deflink.u.mgd.csa.waiting_bcn) ++ if (ieee80211_is_csa_in_progress(sdata)) + return; + + if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) diff --git a/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch b/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch new file mode 100644 index 0000000..3da0679 --- /dev/null +++ b/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch @@ -0,0 +1,136 @@ +From: Maharaja Kennadyrajan +Date: Fri, 18 Jul 2025 11:38:37 +0530 +Subject: [PATCH] wifi: mac80211: extend connection monitoring for MLO + +Currently, reset connection monitor (ieee80211_sta_reset_conn_monitor()) +timer is handled only for non-AP non-MLD STA and do not support non-AP MLD +STA. The current implementation checks for the CSA active and update the +monitor timer with the timeout value of deflink and reset the timer based +on the deflink's timeout value else schedule the connection loss work when +the deflink is timed out and it won't work for the non-AP MLD STA. + +Handle the reset connection monitor timer for non-AP MLD STA by updating +the monitor timer with the timeout value which is determined based on the +link that will expire last among all the links in MLO. If at least one link +has not timed out, the timer is updated accordingly with the latest timeout +value else schedule the connection loss work when all links have timed out. + +Remove the MLO-related WARN_ON() checks in the beacon and connection +monitoring logic code paths as they support MLO now. + +Signed-off-by: Maharaja Kennadyrajan +Link: https://patch.msgid.link/20250718060837.59371-5-maharaja.kennadyrajan@oss.qualcomm.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4300,9 +4300,6 @@ static void ieee80211_mgd_probe_ap_send( + + lockdep_assert_wiphy(sdata->local->hw.wiphy); + +- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- + /* + * Try sending broadcast probe requests for the last three + * probe requests after the first ones failed since some +@@ -4348,9 +4345,6 @@ static void ieee80211_mgd_probe_ap(struc + + lockdep_assert_wiphy(sdata->local->hw.wiphy); + +- if (WARN_ON_ONCE(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- + if (!ieee80211_sdata_running(sdata)) + return; + +@@ -8440,36 +8434,70 @@ static void ieee80211_sta_bcn_mon_timer( + &sdata->u.mgd.beacon_connection_loss_work); + } + ++static unsigned long ++ieee80211_latest_active_link_conn_timeout(struct ieee80211_sub_if_data *sdata) ++{ ++ unsigned long latest_timeout; ++ unsigned int link_id; ++ struct sta_info *sta; ++ ++ guard(rcu)(); ++ ++ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr); ++ if (!sta) ++ return 0; ++ ++ for (link_id = 0; link_id < ARRAY_SIZE(sta->link); ++ link_id++) { ++ struct link_sta_info *link_sta; ++ unsigned long timeout; ++ ++ link_sta = rcu_dereference(sta->link[link_id]); ++ if (!link_sta) ++ continue; ++ ++ timeout = link_sta->status_stats.last_ack; ++ if (time_before(timeout, link_sta->rx_stats.last_rx)) ++ timeout = link_sta->rx_stats.last_rx; ++ ++ timeout += IEEE80211_CONNECTION_IDLE_TIME; ++ ++ /* ++ * latest_timeout holds the timeout of the link ++ * that will expire last among all links in an ++ * non-AP MLD STA. This ensures that the connection ++ * monitor timer is only reset if at least one link ++ * is still active, and it is scheduled to fire at ++ * the latest possible timeout. ++ */ ++ if (time_is_after_jiffies(timeout) && ++ time_after(timeout, latest_timeout)) ++ latest_timeout = timeout; ++ } ++ ++ return latest_timeout; ++} ++ + static void ieee80211_sta_conn_mon_timer(struct timer_list *t) + { + struct ieee80211_sub_if_data *sdata = + timer_container_of(sdata, t, u.mgd.conn_mon_timer); + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; +- struct sta_info *sta; +- unsigned long timeout; ++ unsigned long latest_timeout; + +- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- +- if (sdata->vif.bss_conf.csa_active && +- !sdata->deflink.u.mgd.csa.waiting_bcn) +- return; +- +- sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr); +- if (!sta) ++ if (ieee80211_is_csa_in_progress(sdata)) + return; + +- timeout = sta->deflink.status_stats.last_ack; +- if (time_before(sta->deflink.status_stats.last_ack, sta->deflink.rx_stats.last_rx)) +- timeout = sta->deflink.rx_stats.last_rx; +- timeout += IEEE80211_CONNECTION_IDLE_TIME; ++ latest_timeout = ieee80211_latest_active_link_conn_timeout(sdata); + +- /* If timeout is after now, then update timer to fire at ++ /* ++ * If latest timeout is after now, then update timer to fire at + * the later date, but do not actually probe at this time. + */ +- if (time_is_after_jiffies(timeout)) { +- mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout)); ++ if (latest_timeout) { ++ mod_timer(&ifmgd->conn_mon_timer, ++ round_jiffies_up(latest_timeout)); + return; + } + diff --git a/patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch b/patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch new file mode 100644 index 0000000..457a889 --- /dev/null +++ b/patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch @@ -0,0 +1,25 @@ +From: Lorenzo Bianconi +Date: Tue, 26 Aug 2025 13:54:31 +0200 +Subject: [PATCH] wifi: mac80211: Make CONNECTION_MONITOR optional for MLO sta + +Since commit '1bc892d76a6f ("wifi: mac80211: extend connection +monitoring for MLO")' mac80211 supports connection monitor for MLO +client interfaces. Remove the CONNECTION_MONITOR requirement in +ieee80211_register_hw routine. + +Fixes: 1bc892d76a6f ("wifi: mac80211: extend connection monitoring for MLO") +Signed-off-by: Lorenzo Bianconi +--- + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1179,9 +1179,6 @@ int ieee80211_register_hw(struct ieee802 + if (WARN_ON(!ieee80211_hw_check(hw, MFP_CAPABLE))) + return -EINVAL; + +- if (WARN_ON(!ieee80211_hw_check(hw, CONNECTION_MONITOR))) +- return -EINVAL; +- + if (WARN_ON(ieee80211_hw_check(hw, NEED_DTIM_BEFORE_ASSOC))) + return -EINVAL; + diff --git a/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch b/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch new file mode 100644 index 0000000..fe9db05 --- /dev/null +++ b/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch @@ -0,0 +1,372 @@ +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3559,6 +3559,27 @@ static int ieee80211_set_bitrate_mask(st + return 0; + } + ++bool ieee80211_scanning_busy(struct ieee80211_local *local, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct cfg80211_scan_request *scan_req; ++ struct wiphy *wiphy = local->hw.wiphy; ++ u32 mask; ++ ++ if (list_empty(&local->roc_list) && !local->scanning) ++ return false; ++ ++ if (!wiphy->n_radio) ++ return true; ++ ++ mask = ieee80211_offchannel_radio_mask(local); ++ scan_req = wiphy_dereference(wiphy, local->scan_req); ++ if (scan_req) ++ mask |= ieee80211_scan_req_radio_mask(local, scan_req); ++ ++ return mask & ieee80211_chandef_radio_mask(local, chandef); ++} ++ + static int ieee80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, +@@ -3572,7 +3593,7 @@ static int ieee80211_start_radar_detecti + + lockdep_assert_wiphy(local->hw.wiphy); + +- if (!list_empty(&local->roc_list) || local->scanning) ++ if (ieee80211_scanning_busy(local, chandef)) + return -EBUSY; + + link_data = sdata_dereference(sdata->link[link_id], sdata); +@@ -4064,7 +4085,7 @@ __ieee80211_channel_switch(struct wiphy + + lockdep_assert_wiphy(local->hw.wiphy); + +- if (!list_empty(&local->roc_list) || local->scanning) ++ if (ieee80211_scanning_busy(local, ¶ms->chandef)) + return -EBUSY; + + if (sdata->wdev.links[link_id].cac_started) +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -644,14 +644,24 @@ ieee80211_find_chanctx(struct ieee80211_ + return NULL; + } + +-bool ieee80211_is_radar_required(struct ieee80211_local *local) ++bool ieee80211_is_radar_required(struct ieee80211_local *local, u32 radio_mask) + { ++ struct ieee80211_chanctx_conf *conf; + struct ieee80211_link_data *link; + + lockdep_assert_wiphy(local->hw.wiphy); + + for_each_sdata_link(local, link) { +- if (link->radar_required) ++ if (!link->radar_required) ++ continue; ++ if (!local->hw.wiphy->n_radio) ++ return true; ++ ++ conf = wiphy_dereference(local->hw.wiphy, link->conf->chanctx_conf); ++ if (!conf) ++ continue; ++ ++ if (conf->radio_idx >= 0 && (radio_mask & BIT(conf->radio_idx))) + return true; + } + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1988,6 +1988,12 @@ int ieee80211_mesh_finish_csa(struct iee + u64 *changed); + + /* scan/BSS handling */ ++u32 ieee80211_scan_req_radio_mask(struct ieee80211_local *local, ++ struct cfg80211_scan_request *req); ++bool ieee80211_scanning_busy(struct ieee80211_local *local, ++ struct cfg80211_chan_def *chandef); ++u32 ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata, ++ u32 radio_mask); + void ieee80211_scan_work(struct wiphy *wiphy, struct wiphy_work *work); + int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, +@@ -2026,6 +2032,7 @@ void ieee80211_sched_scan_stopped_work(s + /* off-channel/mgmt-tx */ + void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); + void ieee80211_offchannel_return(struct ieee80211_local *local); ++u32 ieee80211_offchannel_radio_mask(struct ieee80211_local *local); + void ieee80211_roc_setup(struct ieee80211_local *local); + void ieee80211_start_next_roc(struct ieee80211_local *local); + void ieee80211_reconfig_roc(struct ieee80211_local *local); +@@ -2673,6 +2680,8 @@ bool ieee80211_chandef_s1g_oper(const st + struct cfg80211_chan_def *chandef); + void ieee80211_chandef_downgrade(struct cfg80211_chan_def *chandef, + struct ieee80211_conn_settings *conn); ++u32 ieee80211_chandef_radio_mask(struct ieee80211_local *local, ++ struct cfg80211_chan_def *chandef); + static inline void + ieee80211_chanreq_downgrade(struct ieee80211_chan_req *chanreq, + struct ieee80211_conn_settings *conn) +@@ -2729,7 +2738,7 @@ void ieee80211_recalc_chanctx_min_def(st + struct ieee80211_chanctx *ctx, + struct ieee80211_link_data *rsvd_for, + bool check_reserved); +-bool ieee80211_is_radar_required(struct ieee80211_local *local); ++bool ieee80211_is_radar_required(struct ieee80211_local *local, u32 radio_mask); + + void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work); + void ieee80211_dfs_cac_cancel(struct ieee80211_local *local, +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -168,6 +168,35 @@ void ieee80211_offchannel_return(struct + false); + } + ++u32 ieee80211_offchannel_radio_mask(struct ieee80211_local *local) ++{ ++ const struct wiphy_radio *radio; ++ struct ieee80211_roc_work *roc; ++ u32 mask = 0; ++ int r; ++ ++ for (r = 0; r < local->hw.wiphy->n_radio; r++) { ++ radio = &local->hw.wiphy->radio[r]; ++ ++ list_for_each_entry(roc, &local->roc_list, list) { ++ struct cfg80211_chan_def chandef = {}; ++ ++ if (!roc->started) ++ continue; ++ ++ cfg80211_chandef_create(&chandef, roc->chan, ++ NL80211_CHAN_NO_HT); ++ if (!cfg80211_radio_chandef_valid(radio, &chandef)) ++ continue; ++ ++ mask |= BIT(r); ++ break; ++ } ++ } ++ ++ return mask; ++} ++ + static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) + { + /* was never transmitted */ +@@ -566,7 +595,9 @@ static int ieee80211_start_roc_work(stru + enum ieee80211_roc_type type) + { + struct ieee80211_roc_work *roc, *tmp; ++ struct cfg80211_chan_def chandef = {}; + bool queued = false, combine_started = true; ++ u32 radio_mask; + int ret; + + lockdep_assert_wiphy(local->hw.wiphy); +@@ -578,6 +609,12 @@ static int ieee80211_start_roc_work(stru + if (!local->emulate_chanctx && !local->ops->remain_on_channel) + return -EOPNOTSUPP; + ++ cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); ++ radio_mask = ieee80211_chandef_radio_mask(local, &chandef); ++ if (!ieee80211_can_leave_ch(sdata, radio_mask) && ++ !ieee80211_scanning_busy(local, &chandef)) ++ return -EBUSY; ++ + roc = kzalloc(sizeof(*roc), GFP_KERNEL); + if (!roc) + return -ENOMEM; +@@ -613,8 +650,7 @@ static int ieee80211_start_roc_work(stru + } + + /* if there's no need to queue, handle it immediately */ +- if (list_empty(&local->roc_list) && +- !local->scanning && !ieee80211_is_radar_required(local)) { ++ if (list_empty(&local->roc_list) && !local->scanning) { + /* if not HW assist, just queue & schedule work */ + if (!local->ops->remain_on_channel) { + list_add_tail(&roc->list, &local->roc_list); +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -586,36 +586,83 @@ static int ieee80211_start_sw_scan(struc + return 0; + } + +-static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata) ++u32 ieee80211_scan_req_radio_mask(struct ieee80211_local *local, ++ struct cfg80211_scan_request *req) ++{ ++ const struct wiphy_radio *radio; ++ u32 mask = 0; ++ int i, r; ++ ++ for (r = 0; r < local->hw.wiphy->n_radio; r++) { ++ radio = &local->hw.wiphy->radio[r]; ++ ++ for (i = 0; i < req->n_channels; i++) { ++ struct cfg80211_chan_def chandef = {}; ++ ++ chandef.chan = req->channels[i]; ++ cfg80211_chandef_create(&chandef, req->channels[i], ++ NL80211_CHAN_NO_HT); ++ if (!cfg80211_radio_chandef_valid(radio, &chandef)) ++ continue; ++ ++ mask |= BIT(r); ++ break; ++ } ++ } ++ ++ return mask; ++} ++ ++u32 ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata, ++ u32 radio_mask) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *sdata_iter; ++ struct wiphy *wiphy = local->hw.wiphy; ++ struct ieee80211_chanctx_conf *conf; ++ struct ieee80211_link_data *link; + unsigned int link_id; + + lockdep_assert_wiphy(local->hw.wiphy); + +- if (!ieee80211_is_radar_required(local)) ++ if (!ieee80211_is_radar_required(local, radio_mask)) + return true; + + if (!regulatory_pre_cac_allowed(local->hw.wiphy)) + return false; + + list_for_each_entry(sdata_iter, &local->interfaces, list) { +- for_each_valid_link(&sdata_iter->wdev, link_id) +- if (sdata_iter->wdev.links[link_id].cac_started) ++ for_each_valid_link(&sdata_iter->wdev, link_id) { ++ if (!sdata_iter->wdev.links[link_id].cac_started) ++ continue; ++ ++ if (!wiphy->n_radio) + return false; ++ ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ continue; ++ ++ conf = wiphy_dereference(wiphy, link->conf->chanctx_conf); ++ if (!conf) ++ continue; ++ ++ if (conf->radio_idx >= 0 && ++ (radio_mask & BIT(conf->radio_idx))) ++ return false; ++ } + } + + return true; + } + + static bool ieee80211_can_scan(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata) ++ struct ieee80211_sub_if_data *sdata, ++ u32 radio_mask) + { +- if (!__ieee80211_can_leave_ch(sdata)) +- return false; +- +- if (!list_empty(&local->roc_list)) ++ if (!list_empty(&local->roc_list) && ++ (!local->hw.wiphy->n_radio || ++ (radio_mask & ieee80211_offchannel_radio_mask(local)))) + return false; + + if (sdata->vif.type == NL80211_IFTYPE_STATION && +@@ -627,15 +674,22 @@ static bool ieee80211_can_scan(struct ie + + void ieee80211_run_deferred_scan(struct ieee80211_local *local) + { ++ struct ieee80211_sub_if_data *sdata; ++ struct cfg80211_scan_request *req; ++ u32 radio_mask; ++ + lockdep_assert_wiphy(local->hw.wiphy); + +- if (!local->scan_req || local->scanning) ++ req = wiphy_dereference(local->hw.wiphy, local->scan_req); ++ if (!req || local->scanning) ++ return; ++ ++ radio_mask = ieee80211_scan_req_radio_mask(local, req); ++ sdata = wiphy_dereference(local->hw.wiphy, local->scan_sdata); ++ if (!ieee80211_can_leave_ch(sdata, radio_mask)) + return; + +- if (!ieee80211_can_scan(local, +- rcu_dereference_protected( +- local->scan_sdata, +- lockdep_is_held(&local->hw.wiphy->mtx)))) ++ if (!ieee80211_can_scan(local, sdata, radio_mask)) + return; + + wiphy_delayed_work_queue(local->hw.wiphy, &local->scan_work, +@@ -718,6 +772,7 @@ static int __ieee80211_start_scan(struct + { + struct ieee80211_local *local = sdata->local; + bool hw_scan = local->ops->hw_scan; ++ u32 radio_mask; + int rc; + + lockdep_assert_wiphy(local->hw.wiphy); +@@ -732,10 +787,11 @@ static int __ieee80211_start_scan(struct + !(sdata->vif.active_links & BIT(req->tsf_report_link_id))) + return -EINVAL; + +- if (!__ieee80211_can_leave_ch(sdata)) ++ radio_mask = ieee80211_scan_req_radio_mask(local, req); ++ if (!ieee80211_can_leave_ch(sdata, radio_mask)) + return -EBUSY; + +- if (!ieee80211_can_scan(local, sdata)) { ++ if (!ieee80211_can_scan(local, sdata, radio_mask)) { + /* wait for the work to finish/time out */ + rcu_assign_pointer(local->scan_req, req); + rcu_assign_pointer(local->scan_sdata, sdata); +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -877,6 +877,23 @@ struct wireless_dev *ieee80211_vif_to_wd + } + EXPORT_SYMBOL_GPL(ieee80211_vif_to_wdev); + ++u32 ieee80211_chandef_radio_mask(struct ieee80211_local *local, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct wiphy *wiphy = local->hw.wiphy; ++ const struct wiphy_radio *radio; ++ u32 mask = 0; ++ int i; ++ ++ for (i = 0; i < wiphy->n_radio; i++) { ++ radio = &wiphy->radio[i]; ++ if (cfg80211_radio_chandef_valid(radio, chandef)) ++ mask |= BIT(i); ++ } ++ ++ return mask; ++} ++ + /* + * Nothing should have been stuffed into the workqueue during + * the suspend->resume cycle. Since we can't check each caller +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2955,6 +2955,9 @@ bool cfg80211_radio_chandef_valid(const + { + u32 freq, width; + ++ if (!cfg80211_chandef_valid(chandef)) ++ return false; ++ + freq = ieee80211_chandef_to_khz(chandef); + width = cfg80211_chandef_get_width(chandef); + if (!ieee80211_radio_freq_range_valid(radio, freq, width)) diff --git a/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch b/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch new file mode 100644 index 0000000..b34465f --- /dev/null +++ b/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch @@ -0,0 +1,140 @@ +From: Felix Fietkau +Date: Wed, 6 Aug 2025 10:49:54 +0200 +Subject: [PATCH] mac80211: factor out part of + ieee80211_calc_expected_tx_airtime + +Create ieee80211_rate_expected_tx_airtime helper function, which returns +the expected tx airtime for a given rate and packet length in units of +1024 usec, for more accuracy. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -685,7 +685,7 @@ static int ieee80211_fill_rx_status(stru + if (ieee80211_fill_rate_info(hw, stat, band, ri)) + return 0; + +- if (!ieee80211_rate_valid(rate)) ++ if (!rate || !ieee80211_rate_valid(rate)) + return -1; + + if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) +@@ -753,6 +753,53 @@ u32 ieee80211_calc_tx_airtime(struct iee + } + EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime); + ++u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw, ++ struct ieee80211_tx_rate *tx_rate, ++ struct rate_info *ri, ++ enum nl80211_band band, ++ bool ampdu, int len) ++{ ++ struct ieee80211_rx_status stat; ++ u32 duration, overhead; ++ u8 agg_shift; ++ ++ if (ieee80211_fill_rx_status(&stat, hw, tx_rate, ri, band, len)) ++ return 0; ++ ++ if (stat.encoding == RX_ENC_LEGACY || !ampdu) ++ return ieee80211_calc_rx_airtime(hw, &stat, len) * 1024; ++ ++ duration = ieee80211_get_rate_duration(hw, &stat, &overhead); ++ ++ /* ++ * Assume that HT/VHT transmission on any AC except VO will ++ * use aggregation. Since we don't have reliable reporting ++ * of aggregation length, assume an average size based on the ++ * tx rate. ++ * This will not be very accurate, but much better than simply ++ * assuming un-aggregated tx in all cases. ++ */ ++ if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */ ++ agg_shift = 1; ++ else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */ ++ agg_shift = 2; ++ else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */ ++ agg_shift = 3; ++ else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */ ++ agg_shift = 4; ++ else if (stat.encoding != RX_ENC_HE || ++ duration > 20 * 1024) /* <= HE40 MCS6 2S */ ++ agg_shift = 5; ++ else ++ agg_shift = 6; ++ ++ duration *= len; ++ duration /= AVG_PKT_SIZE; ++ duration += (overhead * 1024 >> agg_shift); ++ ++ return duration; ++} ++ + u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *pubsta, +@@ -775,45 +822,13 @@ u32 ieee80211_calc_expected_tx_airtime(s + if (pubsta) { + struct sta_info *sta = container_of(pubsta, struct sta_info, + sta); +- struct ieee80211_rx_status stat; + struct ieee80211_tx_rate *tx_rate = &sta->deflink.tx_stats.last_rate; + struct rate_info *ri = &sta->deflink.tx_stats.last_rate_info; +- u32 duration, overhead; +- u8 agg_shift; +- +- if (ieee80211_fill_rx_status(&stat, hw, tx_rate, ri, band, len)) +- return 0; +- +- if (stat.encoding == RX_ENC_LEGACY || !ampdu) +- return ieee80211_calc_rx_airtime(hw, &stat, len); +- +- duration = ieee80211_get_rate_duration(hw, &stat, &overhead); +- /* +- * Assume that HT/VHT transmission on any AC except VO will +- * use aggregation. Since we don't have reliable reporting +- * of aggregation length, assume an average size based on the +- * tx rate. +- * This will not be very accurate, but much better than simply +- * assuming un-aggregated tx in all cases. +- */ +- if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */ +- agg_shift = 1; +- else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */ +- agg_shift = 2; +- else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */ +- agg_shift = 3; +- else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */ +- agg_shift = 4; +- else if (stat.encoding != RX_ENC_HE || +- duration > 20 * 1024) /* <= HE40 MCS6 2S */ +- agg_shift = 5; +- else +- agg_shift = 6; ++ u32 duration; + +- duration *= len; +- duration /= AVG_PKT_SIZE; ++ duration = ieee80211_rate_expected_tx_airtime(hw, tx_rate, ri, ++ band, true, len); + duration /= 1024; +- duration += (overhead >> agg_shift); + + return max_t(u32, duration, 4); + } +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2789,6 +2789,11 @@ u8 *ieee80211_get_bssid(struct ieee80211 + + extern const struct ethtool_ops ieee80211_ethtool_ops; + ++u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw, ++ struct ieee80211_tx_rate *tx_rate, ++ struct rate_info *ri, ++ enum nl80211_band band, ++ bool ampdu, int len); + u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *pubsta, diff --git a/patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch b/patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch new file mode 100644 index 0000000..cc860b7 --- /dev/null +++ b/patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch @@ -0,0 +1,53 @@ +From: Felix Fietkau +Date: Wed, 6 Aug 2025 10:52:03 +0200 +Subject: [PATCH] mac80211: estimate expected throughput if not provided by + driver/rc + +Estimate the tx throughput based on the expected per-packet tx time. +This is useful for mesh implementations that rely on expected throughput, +e.g. 802.11s or batman-adv. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2648,6 +2648,29 @@ static void sta_set_mesh_sinfo(struct st + } + #endif + ++static u32 sta_estimate_expected_throughput(struct sta_info *sta, ++ struct station_info *sinfo) ++{ ++ struct ieee80211_sub_if_data *sdata = sta->sdata; ++ struct ieee80211_local *local = sdata->local; ++ struct rate_info *ri = &sinfo->txrate; ++ struct ieee80211_hw *hw = &local->hw; ++ struct ieee80211_chanctx_conf *conf; ++ u32 duration; ++ u8 band = 0; ++ ++ conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); ++ if (conf) ++ band = conf->def.chan->band; ++ ++ duration = ieee80211_rate_expected_tx_airtime(hw, NULL, ri, band, true, 1024); ++ duration += duration >> 4; /* add assumed packet error rate of ~6% */ ++ if (!duration) ++ return 0; ++ ++ return ((1024 * USEC_PER_SEC) / duration) * 8; ++} ++ + void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, + bool tidstats) + { +@@ -2871,6 +2894,8 @@ void sta_set_sinfo(struct sta_info *sta, + sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); + + thr = sta_get_expected_throughput(sta); ++ if (!thr && (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) ++ thr = sta_estimate_expected_throughput(sta, sinfo); + + if (thr != 0) { + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT); diff --git a/patches/subsys/370-wifi-mac80211-add-MLO-support-to-ieee80211_probe_cli.patch b/patches/subsys/370-wifi-mac80211-add-MLO-support-to-ieee80211_probe_cli.patch new file mode 100644 index 0000000..1f9d6a1 --- /dev/null +++ b/patches/subsys/370-wifi-mac80211-add-MLO-support-to-ieee80211_probe_cli.patch @@ -0,0 +1,64 @@ +From: Felix Fietkau +Date: Thu, 28 Aug 2025 14:41:57 +0200 +Subject: [PATCH] wifi: mac80211: add MLO support to ieee80211_probe_client + +Use the first available link to probe the client. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4320,7 +4320,9 @@ static int ieee80211_probe_client(struct + struct ieee80211_tx_info *info; + struct sta_info *sta; + struct ieee80211_chanctx_conf *chanctx_conf; ++ struct ieee80211_bss_conf *link_conf; + enum nl80211_band band; ++ u8 link_id; + int ret; + + /* the lock is needed to assign the cookie later */ +@@ -4335,7 +4337,23 @@ static int ieee80211_probe_client(struct + + qos = sta->sta.wme; + +- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); ++ if (ieee80211_vif_is_mld(&sdata->vif)) { ++ if (sta->sta.valid_links) ++ link_id = ffs(sta->sta.valid_links) - 1; ++ else ++ link_id = sta->deflink.link_id; ++ ++ link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ if (unlikely(!link_conf)) { ++ ret = -ENOLINK; ++ goto unlock; ++ } ++ } else { ++ link_id = IEEE80211_LINK_UNSPECIFIED; ++ link_conf = &sdata->vif.bss_conf; ++ } ++ ++ chanctx_conf = rcu_dereference(link_conf->chanctx_conf); + if (WARN_ON(!chanctx_conf)) { + ret = -EINVAL; + goto unlock; +@@ -4367,14 +4385,15 @@ static int ieee80211_probe_client(struct + nullfunc->frame_control = fc; + nullfunc->duration_id = 0; + memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); +- memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); +- memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); ++ memcpy(nullfunc->addr2, link_conf->addr, ETH_ALEN); ++ memcpy(nullfunc->addr3, link_conf->addr, ETH_ALEN); + nullfunc->seq_ctrl = 0; + + info = IEEE80211_SKB_CB(skb); + + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | + IEEE80211_TX_INTFL_NL80211_FRAME_TX; ++ info->control.flags |= u32_encode_bits(link_id, IEEE80211_TX_CTRL_MLO_LINK); + info->band = band; + + skb_set_queue_mapping(skb, IEEE80211_AC_VO); diff --git a/patches/subsys/600-mac80211-allow-vht-on-2g.patch b/patches/subsys/600-mac80211-allow-vht-on-2g.patch new file mode 100644 index 0000000..294e09e --- /dev/null +++ b/patches/subsys/600-mac80211-allow-vht-on-2g.patch @@ -0,0 +1,36 @@ +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -137,7 +137,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(stru + have_80mhz = false; + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | +- IEEE80211_CHAN_NO_80MHZ)) ++ IEEE80211_CHAN_NO_80MHZ) & ++ (sband->band != NL80211_BAND_2GHZ)) + continue; + + have_80mhz = true; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1329,7 +1329,8 @@ static int ieee80211_put_preq_ies_band(s + /* Check if any channel in this sband supports at least 80 MHz */ + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | +- IEEE80211_CHAN_NO_80MHZ)) ++ IEEE80211_CHAN_NO_80MHZ) & ++ (sband->band != NL80211_BAND_2GHZ)) + continue; + + have_80mhz = true; +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -5760,7 +5760,8 @@ ieee80211_determine_our_sta_mode(struct + /* Allow VHT if at least one channel on the sband supports 80 MHz */ + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | +- IEEE80211_CHAN_NO_80MHZ)) ++ IEEE80211_CHAN_NO_80MHZ) & ++ (sband->band != NL80211_BAND_2GHZ)) + continue; + + have_80mhz = true; diff --git a/ralink.mk b/ralink.mk new file mode 100644 index 0000000..6925d9c --- /dev/null +++ b/ralink.mk @@ -0,0 +1,146 @@ +PKG_DRIVERS += \ + rt2x00-lib rt2x00-pci rt2x00-usb rt2x00-mmio \ + rt2800-lib rt2800-mmio rt2800-pci rt2800-soc rt2800-usb \ + rt61-pci rt73-usb + +PKG_CONFIG_DEPENDS += \ + CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS \ + CONFIG_PACKAGE_RT2X00_DEBUG + +config-$(call config_package,rt2x00-lib) += RT2X00 RT2X00_LIB +config-$(call config_package,rt2x00-pci) += RT2X00_LIB_PCI +config-$(call config_package,rt2x00-mmio) += RT2X00_LIB_MMIO +config-$(call config_package,rt2x00-usb) += RT2X00_LIB_USB +config-$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) += RT2X00_LIB_DEBUGFS +config-$(CONFIG_PACKAGE_RT2X00_DEBUG) += RT2X00_DEBUG + +config-$(call config_package,rt2400-pci) += RT2400PCI +config-$(call config_package,rt2500-pci) += RT2500PCI +config-$(call config_package,rt2500-usb) += RT2500USB +config-$(call config_package,rt61-pci) += RT61PCI +config-$(call config_package,rt73-usb) += RT73USB + +config-$(call config_package,rt2800-lib) += RT2800_LIB + +config-$(call config_package,rt2800-soc) += RT2800SOC +config-$(call config_package,rt2800-pci) += RT2800PCI +config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290 + +config-$(call config_package,rt2800-usb) += RT2800USB +config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX RT2800USB_UNKNOWN + +define KernelPackage/rt2x00/Default + $(call KernelPackage/mac80211/Default) + TITLE:=Ralink Drivers for RT2x00 cards +endef + +define KernelPackage/rt2x00-lib +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 + TITLE+= (LIB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00lib.ko + MENU:=1 +endef + +define KernelPackage/rt2x00-lib/config + if PACKAGE_kmod-rt2x00-lib + + config PACKAGE_RT2X00_LIB_DEBUGFS + bool "Enable rt2x00 debugfs support" + depends on PACKAGE_MAC80211_DEBUGFS + help + Enable creation of debugfs files for the rt2x00 drivers. + These debugfs files support both reading and writing of the + most important register types of the rt2x00 hardware. + + config PACKAGE_RT2X00_DEBUG + bool "Enable rt2x00 debug output" + help + Enable debugging output for all rt2x00 modules + + endif +endef + +define KernelPackage/rt2x00-mmio +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib + HIDDEN:=1 + TITLE+= (MMIO) + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.ko +endef + +define KernelPackage/rt2x00-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-mmio +kmod-rt2x00-lib + HIDDEN:=1 + TITLE+= (PCI) + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00pci.ko + AUTOLOAD:=$(call AutoProbe,rt2x00pci) +endef + +define KernelPackage/rt2x00-usb +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core + HIDDEN:=1 + TITLE+= (USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00usb.ko + AUTOLOAD:=$(call AutoProbe,rt2x00usb) +endef + +define KernelPackage/rt2800-lib +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt + HIDDEN:=1 + TITLE+= (rt2800 LIB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800lib.ko +endef + +define KernelPackage/rt2800-mmio +$(call KernelPackage/rt2x00/Default) + TITLE += (RT28xx/RT3xxx MMIO) + DEPENDS += +kmod-rt2800-lib +kmod-rt2x00-mmio + HIDDEN:=1 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800mmio.ko +endef + +define KernelPackage/rt2800-soc +$(call KernelPackage/rt2x00/Default) + DEPENDS += @(TARGET_ramips_rt288x||TARGET_ramips_rt305x||TARGET_ramips_rt3883||TARGET_ramips_mt7620) +kmod-rt2800-mmio +kmod-rt2800-lib + TITLE += (RT28xx/RT3xxx SoC) + FILES := \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00soc.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800soc.ko + AUTOLOAD:=$(call AutoProbe,rt2800soc) +endef + +define KernelPackage/rt2800-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-rt2800-mmio +kmod-eeprom-93cx6 +rt2800-pci-firmware + TITLE+= (RT2860 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800pci.ko + AUTOLOAD:=$(call AutoProbe,rt2800pci) +endef + +define KernelPackage/rt2800-usb +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt +rt2800-usb-firmware + TITLE+= (RT2870 USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800usb.ko + AUTOLOAD:=$(call AutoProbe,rt2800usb) +endef + +define KernelPackage/rt61-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-eeprom-93cx6 +kmod-lib-crc-itu-t +rt61-pci-firmware + TITLE+= (RT2x61 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt61pci.ko + AUTOLOAD:=$(call AutoProbe,rt61pci) +endef + +define KernelPackage/rt73-usb + $(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-lib-crc-itu-t +rt73-usb-firmware + TITLE+= (RT73 USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt73usb.ko + AUTOLOAD:=$(call AutoProbe,rt73usb) +endef diff --git a/realtek.mk b/realtek.mk new file mode 100644 index 0000000..e16ffa8 --- /dev/null +++ b/realtek.mk @@ -0,0 +1,590 @@ +PKG_DRIVERS += \ + rtlwifi rtlwifi-pci rtlwifi-btcoexist rtlwifi-usb rtl8192c-common rtl8192d-common \ + rtl8192ce rtl8192se rtl8192de rtl8192cu rtl8192du rtl8723-common rtl8723be \ + rtl8723bs rtl8821ae rtl8xxxu rtw88 rtw88-pci rtw88-usb rtw88-sdio rtw88-8821c \ + rtw88-8822b rtw88-8822c rtw88-8723x rtw88-8723d rtw88-8821ce rtw88-8821cu \ + rtw88-8822be rtw88-8822bu rtw88-8822ce rtw88-8822cs rtw88-8822cu rtw88-8723de \ + rtw88-8723ds rtw88-88xxa rtw88-8821a rtw88-8812a rtw88-8821au rtw88-8812au \ + rtw88-8814a rtw88-8814ae rtw88-8814au \ + rtw88-8723du rtw89 rtw89-pci rtw89-8851be rtw89-8852ae rtw89-8852b-common \ + rtw89-8852be rtw89-8852ce rtw89-8922ae + +config-$(call config_package,rtlwifi) += RTL_CARDS RTLWIFI +config-$(call config_package,rtlwifi-pci) += RTLWIFI_PCI +config-$(call config_package,rtlwifi-btcoexist) += RTLBTCOEXIST +config-$(call config_package,rtlwifi-usb) += RTLWIFI_USB +config-$(call config_package,rtl8192c-common) += RTL8192C_COMMON +config-$(call config_package,rtl8192ce) += RTL8192CE +config-$(call config_package,rtl8192se) += RTL8192SE +config-$(call config_package,rtl8192d-common) += RTL8192D_COMMON +config-$(call config_package,rtl8192de) += RTL8192DE +config-$(call config_package,rtl8192du) += RTL8192DU +config-$(call config_package,rtl8192cu) += RTL8192CU +config-$(call config_package,rtl8821ae) += RTL8821AE +config-$(CONFIG_PACKAGE_RTLWIFI_DEBUG) += RTLWIFI_DEBUG + +config-$(call config_package,rtl8xxxu) += RTL8XXXU +config-y += RTL8XXXU_UNTESTED + +config-$(call config_package,rtl8723-common) += RTL8723_COMMON +config-$(call config_package,rtl8723be) += RTL8723BE + +config-$(call config_package,rtl8723bs) += RTL8723BS +config-y += STAGING + +config-$(call config_package,rtw88) += RTW88 RTW88_CORE +config-$(call config_package,rtw88-pci) += RTW88_PCI +config-$(call config_package,rtw88-usb) += RTW88_USB +config-$(call config_package,rtw88-sdio) += RTW88_SDIO +config-$(call config_package,rtw88-8821c) += RTW88_8821C +config-$(call config_package,rtw88-8821ce) += RTW88_8821CE +config-$(call config_package,rtw88-8821cu) += RTW88_8821CU +config-$(call config_package,rtw88-8822b) += RTW88_8822B +config-$(call config_package,rtw88-8822be) += RTW88_8822BE +config-$(call config_package,rtw88-8822bu) += RTW88_8822BU +config-$(call config_package,rtw88-8822c) += RTW88_8822C +config-$(call config_package,rtw88-8822ce) += RTW88_8822CE +config-$(call config_package,rtw88-8822cs) += RTW88_8822CS +config-$(call config_package,rtw88-8822cu) += RTW88_8822CU +config-$(call config_package,rtw88-8723x) += RTW88_8723X +config-$(call config_package,rtw88-8723d) += RTW88_8723D +config-$(call config_package,rtw88-8723de) += RTW88_8723DE +config-$(call config_package,rtw88-8723ds) += RTW88_8723DS +config-$(call config_package,rtw88-8723du) += RTW88_8723DU +config-$(call config_package,rtw88-88xxa) += RTW88_88XXA +config-$(call config_package,rtw88-8821a) += RTW88_8821A +config-$(call config_package,rtw88-8812a) += RTW88_8812A +config-$(call config_package,rtw88-8821au) += RTW88_8821AU +config-$(call config_package,rtw88-8812au) += RTW88_8812AU +config-$(call config_package,rtw88-8814a) += RTW88_8814A +config-$(call config_package,rtw88-8814ae) += RTW88_8814AE +config-$(call config_package,rtw88-8814au) += RTW88_8814AU +config-$(CONFIG_PACKAGE_RTW88_DEBUG) += RTW88_DEBUG +config-$(CONFIG_PACKAGE_RTW88_DEBUGFS) += RTW88_DEBUGFS + +config-$(call config_package,rtw89) += RTW89 RTW89_CORE +config-$(call config_package,rtw89-pci) += RTW89_PCI +config-$(call config_package,rtw89-8851be) += RTW89_8851B RTW89_8851BE +config-$(call config_package,rtw89-8852ae) += RTW89_8852A RTW89_8852AE +config-$(call config_package,rtw89-8852b-common) += RTW89_8852B_COMMON +config-$(call config_package,rtw89-8852be) += RTW89_8852B RTW89_8852BE +config-$(call config_package,rtw89-8852ce) += RTW89_8852C RTW89_8852CE +config-$(call config_package,rtw89-8922ae) += RTW89_8922A RTW89_8922AE +config-$(CONFIG_PACKAGE_RTW89_DEBUG) += RTW89_DEBUG +config-$(CONFIG_PACKAGE_RTW89_DEBUGFS) += RTW89_DEBUGFS +config-$(CONFIG_PACKAGE_RTW89_DEBUGMSG) += RTW89_DEBUGMSG + +define KernelPackage/rtlwifi/config + config PACKAGE_RTLWIFI_DEBUG + bool "Realtek wireless debugging" + depends on PACKAGE_kmod-rtlwifi + help + Say Y, if you want to debug realtek wireless drivers. + +endef + +define KernelPackage/rtlwifi + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek common driver part + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtlwifi.ko + HIDDEN:=1 +endef + +define KernelPackage/rtlwifi-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek common driver part (PCI support) + DEPENDS+= @PCI_SUPPORT +kmod-rtlwifi + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl_pci.ko + AUTOLOAD:=$(call AutoProbe,rtl_pci) + HIDDEN:=1 +endef + +define KernelPackage/rtlwifi-btcoexist + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek BT coexist support + DEPENDS+= +kmod-rtlwifi + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/btcoexist/btcoexist.ko + AUTOLOAD:=$(call AutoProbe,btcoexist) + HIDDEN:=1 +endef + +define KernelPackage/rtlwifi-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek common driver part (USB support) + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-rtlwifi + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl_usb.ko + AUTOLOAD:=$(call AutoProbe,rtl_usb) + HIDDEN:=1 +endef + +define KernelPackage/rtl8192c-common + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192CE/RTL8192CU common support module + DEPENDS+= +kmod-rtlwifi + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192c/rtl8192c-common.ko + HIDDEN:=1 +endef + +define KernelPackage/rtl8192ce + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192CE/RTL8188CE support + DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192c-common +rtl8192ce-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rtl8192ce.ko + AUTOLOAD:=$(call AutoProbe,rtl8192ce) +endef + +define KernelPackage/rtl8192se + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192SE/RTL8191SE support + DEPENDS+= +kmod-rtlwifi-pci +rtl8192se-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rtl8192se.ko + AUTOLOAD:=$(call AutoProbe,rtl8192se) +endef + +define KernelPackage/rtl8192d-common + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192DE/RTL8192DU common support module + DEPENDS+= +kmod-rtlwifi + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192d/rtl8192d-common.ko + HIDDEN:=1 +endef + +define KernelPackage/rtl8192de + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192DE/RTL8188DE support + DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192d-common +rtl8192de-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rtl8192de.ko + AUTOLOAD:=$(call AutoProbe,rtl8192de) +endef + +define KernelPackage/rtl8192du + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192DU support + DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192d-common +rtl8192du-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192du/rtl8192du.ko + AUTOLOAD:=$(call AutoProbe,rtl8192du) +endef + +define KernelPackage/rtl8192cu + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192CU/RTL8188CU support + DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192c-common +rtl8192cu-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rtl8192cu.ko + AUTOLOAD:=$(call AutoProbe,rtl8192cu) +endef + +define KernelPackage/rtl8821ae + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821AE support + DEPENDS+= +kmod-rtlwifi-btcoexist +kmod-rtlwifi-pci +rtl8821ae-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rtl8821ae.ko + AUTOLOAD:=$(call AutoProbe,rtl8821ae) +endef + +define KernelPackage/rtl8xxxu + $(call KernelPackage/mac80211/Default) + TITLE:=alternative Realtek RTL8XXXU support + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211 + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.ko + AUTOLOAD:=$(call AutoProbe,rtl8xxxu) +endef + +define KernelPackage/rtl8xxxu/description + This is an alternative driver for various Realtek RTL8XXX + parts written to utilize the Linux mac80211 stack. + The driver is known to work with a number of RTL8723AU, + RL8188CU, RTL8188RU, RTL8191CU, and RTL8192CU devices + + This driver is under development and has a limited feature + set. In particular it does not yet support 40MHz channels + and power management. However it should have a smaller + memory footprint than the vendor drivers and benetifs + from the in kernel mac80211 stack. + + It can coexist with drivers from drivers/staging/rtl8723au, + drivers/staging/rtl8192u, and drivers/net/wireless/rtlwifi, + but you will need to control which module you wish to load. + + RTL8XXXU_UNTESTED is enabled + This option enables detection of Realtek 8723/8188/8191/8192 WiFi + USB devices which have not been tested directly by the driver + author or reported to be working by third parties. + + Please report your results! +endef + +define KernelPackage/rtw88/config + config PACKAGE_RTW88_DEBUG + bool "Realtek wireless debugging (rtw88)" + depends on PACKAGE_kmod-rtw88 + help + Enable debugging output for rtw88 devices + + config PACKAGE_RTW88_DEBUGFS + bool "Enable rtw88 debugfS support" + select KERNEL_DEBUG_FS + depends on PACKAGE_kmod-rtw88 + help + Select this to see extensive information about + the internal state of rtw88 in debugfs. +endef + +define KernelPackage/rtw88 + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTW88 common part + DEPENDS+= +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_core.ko + AUTOLOAD:=$(call AutoProbe,rtw88_core) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTW88 PCI chips support + DEPENDS+= @PCI_SUPPORT +kmod-rtw88 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko + AUTOLOAD:=$(call AutoProbe,rtw88_pci) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTW88 SDIO chips support + DEPENDS+= +kmod-mmc +kmod-rtw88 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_sdio.ko + AUTOLOAD:=$(call AutoProbe,rtw88_sdio) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTW88 USB chips support + DEPENDS+= @USB_SUPPORT +kmod-rtw88 +kmod-usb-core + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_usb.ko + AUTOLOAD:=$(call AutoProbe,rtw88_usb) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-88xxa + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8812A/RTL8821A family support + DEPENDS+= +@DRIVER_11AC_SUPPORT +kmod-rtw88-usb + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_88xxa.ko + AUTOLOAD:=$(call AutoProbe,rtw88_88xxa) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8821a + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821A family support + DEPENDS+= +kmod-rtw88-88xxa + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821a.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821a) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8812a + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8812A family support + DEPENDS+= +kmod-rtw88-88xxa + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8812a.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8812a) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8814a + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8814A family support + DEPENDS+= +@DRIVER_11AC_SUPPORT +kmod-rtw88 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8814a.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8814a) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8821c + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821C family support + DEPENDS+= +kmod-rtw88 +rtl8821ce-firmware +@DRIVER_11AC_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821c.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821c) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8822b + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822B family support + DEPENDS+= +kmod-rtw88 +rtl8822be-firmware +@DRIVER_11AC_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822b.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822b) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8822c + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822C family support + DEPENDS+= +kmod-rtw88 +rtl8822ce-firmware +@DRIVER_11AC_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822c.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822c) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8723x + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723x family support + DEPENDS+= +kmod-rtw88 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723x.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8723x) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8723d + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723D family support + DEPENDS+= +kmod-rtw88-8723x +rtl8723de-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723d.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8723d) + HIDDEN:=1 +endef + +define KernelPackage/rtw88-8821au + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821AU support + DEPENDS+= +kmod-rtw88-8821a +rtl8821a-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821au.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821au) +endef + +define KernelPackage/rtw88-8812au + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8812AU support + DEPENDS+= +kmod-rtw88-8812a +rtl8812a-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8812au.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8812au) +endef + +define KernelPackage/rtw88-8814ae + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8814AE support + DEPENDS+= +kmod-rtw88-8814a +kmod-rtw88-pci +rtl8814a-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8814ae.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8814ae) +endef + +define KernelPackage/rtw88-8814au + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8814AU support + DEPENDS+= +kmod-rtw88-8814a +kmod-rtw88-usb +rtl8814a-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8814au.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8814au) +endef + +define KernelPackage/rtw88-8821ce + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821CE support + DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8821c + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821ce.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821ce) +endef + +define KernelPackage/rtw88-8821cu + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821CU support + DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8821c + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821cu.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821cu) +endef + +define KernelPackage/rtw88-8822be + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822BE support + DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8822b + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822be.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822be) +endef + +define KernelPackage/rtw88-8822bu + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822BU support + DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8822b + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822bu.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822bu) +endef + +define KernelPackage/rtw88-8822ce + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822CE support + DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8822c + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822ce.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822ce) +endef + +define KernelPackage/rtw88-8822cs + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822CS support + DEPENDS+= +kmod-rtw88-sdio +kmod-rtw88-8822c + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822cs.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822cs) +endef + +define KernelPackage/rtw88-8822cu + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822CU support + DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8822c + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822cu.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822cu) +endef + +define KernelPackage/rtw88-8723de + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723DE support + DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8723d + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723de.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8723de) +endef + +define KernelPackage/rtw88-8723ds + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723DS support + DEPENDS+= +kmod-rtw88-sdio +kmod-rtw88-8723d + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723ds.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8723ds) +endef + +define KernelPackage/rtw88-8723du + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723DU support + DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8723d + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723du.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8723du) +endef + +define KernelPackage/rtl8723-common + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723AE/RTL8723BE common support module + DEPENDS+= +kmod-rtlwifi + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8723com/rtl8723-common.ko + HIDDEN:=1 +endef + +define KernelPackage/rtl8723be + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723AE/RTL8723BE support + DEPENDS+= +kmod-rtlwifi-btcoexist +kmod-rtlwifi-pci +kmod-rtl8723-common +rtl8723be-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rtl8723be.ko + AUTOLOAD:=$(call AutoProbe,rtl8723be) +endef + +define KernelPackage/rtl8723bs + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723BS SDIO Wireless LAN NIC driver (staging) + DEPENDS+=+kmod-mmc +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/staging/rtl8723bs/r8723bs.ko + AUTOLOAD:=$(call AutoProbe,r8723bs) +endef + +define KernelPackage/rtl8723bs/description + This option enables support for RTL8723BS SDIO drivers, such as the wifi found + on the 1st gen Intel Compute Stick, the CHIP and many other Intel Atom and ARM + based devices. +endef + +define KernelPackage/rtw89/config + config PACKAGE_RTW89_DEBUG + bool "Realtek wireless debugging (rtw89)" + depends on PACKAGE_kmod-rtw89 + help + Enable debugging output for rtw89 devices. + + config PACKAGE_RTW89_DEBUGFS + bool "Enable rtw89 debugfs support" + select KERNEL_DEBUG_FS + depends on PACKAGE_kmod-rtw89 + help + Select this to see extensive information about + the internal state of rtw89 in debugfs. + + config PACKAGE_RTW89_DEBUGMSG + bool "Realtek rtw89 debug message support" + depends on PACKAGE_kmod-rtw89 + help + Enable debug message support. +endef + +define KernelPackage/rtw89 + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTW89 core + DEPENDS+= +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_core.ko + AUTOLOAD:=$(call AutoProbe,rtw89_core) + HIDDEN:=1 +endef + +define KernelPackage/rtw89-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTW89 PCI chips support + DEPENDS+= @PCI_SUPPORT +kmod-rtw89 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_pci.ko + AUTOLOAD:=$(call AutoProbe,rtw89_pci) + HIDDEN:=1 +endef + +define KernelPackage/rtw89-8851be + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8851BE support + DEPENDS+= +kmod-rtw89-pci +rtl8851be-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8851b.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8851be.ko + AUTOLOAD:=$(call AutoProbe,rtw89_8851be) +endef + +define KernelPackage/rtw89-8852ae + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8852AE support + DEPENDS+= +kmod-rtw89-pci +rtl8852ae-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852a.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852ae.ko + AUTOLOAD:=$(call AutoProbe,rtw89_8852ae) +endef + +define KernelPackage/rtw89-8852b-common + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8852B family support + DEPENDS+= +kmod-rtw89-pci + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852b_common.ko + AUTOLOAD:=$(call AutoProbe,rtw89_8852b_common) + HIDDEN:=1 +endef + +define KernelPackage/rtw89-8852be + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8852BE support + DEPENDS+= +kmod-rtw89-8852b-common +rtl8852be-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852b.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852be.ko + AUTOLOAD:=$(call AutoProbe,rtw89_8852be) +endef + +define KernelPackage/rtw89-8852ce + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8852CE support + DEPENDS+= +kmod-rtw89-pci +rtl8852ce-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852c.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852ce.ko + AUTOLOAD:=$(call AutoProbe,rtw89_8852ce) +endef + +define KernelPackage/rtw89-8922ae + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8922AE support + DEPENDS+= +kmod-rtw89-pci +rtl8922ae-firmware +@DRIVER_11BE_SUPPORT + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8922a.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8922ae.ko + AUTOLOAD:=$(call AutoProbe,rtw89_8922ae) +endef diff --git a/scripts/import-backports.sh b/scripts/import-backports.sh new file mode 100755 index 0000000..35aa411 --- /dev/null +++ b/scripts/import-backports.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash +BASE=$1; shift + +usage() { + echo "Usage: $0 NNN ..." + exit 1 +} + +check_number() { + case "$1" in + [0-9][0-9][0-9]) return 0;; + esac + return 1; +} + +patch_header() +{ + awk ' + /^(---|\*\*\*|Index:)[ \t][^ \t]|^diff -/ \ + { exit } + { print } + ' +} + +strip_diffstat() +{ + awk ' + /#? .* \| / \ + { eat = eat $0 "\n" + next } + /^#? .* files? changed(, .* insertions?\(\+\))?(, .* deletions?\(-\))?/ \ + { eat = "" + next } + { print eat $0 + eat = "" } + ' +} + +strip_trailing_whitespace() { + sed -e 's:[ '$'\t'']*$::' +} + +fixup_header() { + awk ' + /^From / { next } + /^Subject: / { + sub("Subject: \\[[^\]]*\\]", "Subject: [PATCH]") + } + { print } + ' +} + +check_number "$BASE" || usage + +quilt series > /dev/null || { + echo "Not in quilt directory" + exit 2 +} + +get_next() { + NEW=$BASE + quilt series | while read CUR; do + [ -n "$CUR" ] || break + CUR=${CUR%%-*} + check_number "$CUR" || continue + [ "$CUR" -lt "$NEW" ] && continue + [ "$CUR" -ge "$(($BASE + 100))" ] && continue + NEW="$(($CUR + 1))" + echo $NEW + done | tail -n1 +} + +CUR=$(get_next) +CUR="${CUR:-$BASE}" + +while [ -n "$1" ]; do + FILE="$1"; shift + NAME="$(basename $FILE)" + NAME="${NAME#[0-9]*-}" + echo -n "Processing patch $NAME: " + + [ -e "$FILE" ] || { + echo "file $FILE not found" + exit 1 + } + + grep -qE "$NAME$" patches/series && { + echo "already applied" + continue + } + + quilt new "$CUR-$NAME" || exit 1 + patch_header < "$FILE" | + strip_diffstat | + strip_trailing_whitespace | + fixup_header > "patches/$CUR-$NAME" + + quilt fold < "$FILE" || { + cp "$FILE" ./cur_patch + echo "patch $FILE failed to apply, copied to ./cur_patch" + exit 1 + } + + quilt refresh -p ab --no-index --no-timestamps + + CUR="$(($CUR + 1))" +done + +exit 0